|
| 1 | += UUID References |
| 2 | + |
| 3 | +[NOTE] |
| 4 | +==== |
| 5 | +This is a somewhat advanced, technical section. It is intended to give power |
| 6 | +users more knowledge about the internal function of LibrePCB, as this knowledge |
| 7 | +can be useful to increase productivity and to reduce the likelihood of running |
| 8 | +into troubles caused by broken UUID references. |
| 9 | +
|
| 10 | +More technical details about references between library elements are available |
| 11 | +https://developers.librepcb.org/df/d4f/doc_library.html[here]. |
| 12 | +==== |
| 13 | + |
| 14 | +== Purpose of References |
| 15 | + |
| 16 | +In every EDA tool, libraries and projects are full of cross-references between |
| 17 | +different objects. For example, when attaching a wire to a pin in the schematic, |
| 18 | +the wire has to store a reference to that particular pin to successfully |
| 19 | +restore that connection when you open the schematic the next time. |
| 20 | + |
| 21 | +Many EDA tools use the object's name as reference. For example when you connect |
| 22 | +a wire of the _GND_ net to the pin named _IN+_ of the component with the |
| 23 | +designator _U3_, the schematic editor stores a reference like `U3:IN+` for the |
| 24 | +attached wire in the schematic file. When opening the schematic the next time, |
| 25 | +the editor searches for a component with the designator _U3_ in the project |
| 26 | +library, and then for a pin named _IN+_ within this component to restore the |
| 27 | +wire connection. |
| 28 | + |
| 29 | +This system works, but it comes with a big disadvantage. Whenever you rename |
| 30 | +any referenced object (e.g. renaming pin _IN+_ to _+_), all the references to |
| 31 | +this object will break, causing broken library elements or projects. So in fact |
| 32 | +it is not allowed to ever rename or move things, or you will run into troubles. |
| 33 | +A typical symptom is that the editor throws errors like "Component XYZ not |
| 34 | +found", for example after updating libraries and then opening an older project. |
| 35 | + |
| 36 | +== References in LibrePCB |
| 37 | + |
| 38 | +LibrePCB follows a different approach. Instead of referencing objects by |
| 39 | +their name, it assigns a random identifier to every newly created object, and |
| 40 | +uses this for all the references. In particular, it uses |
| 41 | +https://en.wikipedia.org/wiki/Universally_unique_identifier[universally unique identifiers (UUIDs)] which consist of 36 characters and look like |
| 42 | +_3da6ef2c-03ff-4ed1-a8b8-c8acf2ed0291_. |
| 43 | + |
| 44 | +For example, when you add a pin to a symbol, the editor automatically generates |
| 45 | +and assigns a random UUID to the pin. You may give the pin a human-readable |
| 46 | +name like _IN+_, but the editor gives it a UUID like |
| 47 | +_cc3af4a4-cc26-4548-a026-468e1d689ab3_. This UUID is typically not user-facing, |
| 48 | +so usually you won't ever see it. But behind the scenes, LibrePCB uses this |
| 49 | +UUID for any references. So a wire in the schematic which is attached to |
| 50 | +a pin won't reference the pin like `U3:IN+` in other tools, but like |
| 51 | +`7b8fef14-64f9-4502-8094-7e2c1c0b6e9a:cc3af4a4-cc26-4548-a026-468e1d689ab3` |
| 52 | +where the first UUID refers to the component (_U3_) and the second UUID |
| 53 | +refers to a pin of it (_IN+_). |
| 54 | + |
| 55 | +Now whenever you rename objects like a symbol pin, it will only affect the |
| 56 | +human-readable name, but not its UUID. The UUID of an existing object will |
| 57 | +never change, so all the references to it will stay intact. |
| 58 | + |
| 59 | +== Drawbacks of UUIDs |
| 60 | + |
| 61 | +This system comes with the advantage of keeping references intact even when |
| 62 | +renaming objects, thus avoiding broken library elements or projects after |
| 63 | +renaming or moving things. However, it also comes with some drawbacks you |
| 64 | +should be aware of. |
| 65 | + |
| 66 | +=== Names Are Non-Functional |
| 67 | + |
| 68 | +As LibrePCB itself only considers the UUIDs for making references, in fact |
| 69 | +it does not care about the name of objects. Names are only for _you_, not |
| 70 | +for LibrePCB. |
| 71 | + |
| 72 | +Now when you make substantial renames to existing objects, like renaming pin |
| 73 | +_IN+_ to _IN-_ because you want to swap those two pins of an OpAmp, this will |
| 74 | +change the meaning of the symbol pins. The pin which was _IN+_ before is now |
| 75 | +_IN-_ and vice versa. However, since the underlying UUIDs were not changed, |
| 76 | +for LibrePCB the pin function has not changed either. So if a wire of the net |
| 77 | +_VBAT_ was attached to pin _IN+_ before the rename, that wire will remain |
| 78 | +attached to the same pin after the rename, even though it's now called _IN-_. |
| 79 | + |
| 80 | +So, keep this in mind and be careful when changing the meaning of existing pins. |
| 81 | +In this particular example, it would be better to swap the positions of the |
| 82 | +two OpAmp pins instead of swapping their names, since swapping the positions |
| 83 | +will keep the relation between UUID and pin function. |
| 84 | + |
| 85 | +=== Copy != Duplicate |
| 86 | + |
| 87 | +The LibrePCB library editor allows you to copy existing library elements in |
| 88 | +two different ways, and it is crucial to know the difference of those |
| 89 | +operations to understand in which situation you need which of those. |
| 90 | + |
| 91 | +Copy:: |
| 92 | +The copy operation is provided in the library overview tab, called |
| 93 | +_Copy to Other Library_. This operation will **copy an existing library |
| 94 | +element 1:1 into another library, keeping all its UUIDs**. In fact, this |
| 95 | +operation just copies the files from one library into another. As the UUIDs |
| 96 | +are preserved in this operation, in fact **the copy still represents the same |
| 97 | +object** -- it is _not_ a new, independent symbol. |
| 98 | ++ |
| 99 | +For example when you copy a symbol named _OpAmp_ into another library, and |
| 100 | +you rename the new copy to _Comparator_, in fact you won't have two symbols |
| 101 | +afterwards! Since both symbols still have the same UUID, LibrePCB will pick |
| 102 | +only one of them (the one with the higher version number) and considers the |
| 103 | +other as an (outdated) duplicate. That duplicate won't be listed anywhere, |
| 104 | +so it feels like it is lost. |
| 105 | ++ |
| 106 | +The copy operation is only intended to **override** library elements from |
| 107 | +read-only remote libraries with your own modifications. If you're not happy |
| 108 | +with a library element from our official libraries, you can copy it into your |
| 109 | +local library, modify it, give it a higher version number and save it. LibrePCB |
| 110 | +will then use _your_ library element in place of the original library element. |
| 111 | ++ |
| 112 | +[IMPORTANT] |
| 113 | +==== |
| 114 | +**Except from this particular use-case, the copy operation is usually not the |
| 115 | +right operation.** If used wrongly, it can lead to surprising behavior. |
| 116 | +==== |
| 117 | + |
| 118 | +Save To:: |
| 119 | +This operation is provided in the _Project Library Manager_ and is called |
| 120 | +_Copy elements to local library_. It is exactly the same as the _Copy_ |
| 121 | +operation, just for copying library elements from a project into a library |
| 122 | +rather than between two libraries. It allows to add library elements from |
| 123 | +a project to your local library (keeping their UUIDs), so you can modify the |
| 124 | +elements or reuse them in other projects. |
| 125 | + |
| 126 | +[#duplicate] |
| 127 | +Duplicate:: |
| 128 | +This operation is provided in the library overview tab to duplicate a library |
| 129 | +element within the opened library. **In contrast to the _Copy_ operation, the |
| 130 | +_Duplicate_ operation generates new UUIDs for the duplicated library element |
| 131 | +and all its contained objects.** It is _not_ just a file copy operation. |
| 132 | ++ |
| 133 | +This is the right operation to create a new library element which is similar |
| 134 | +to an existing element, so you don't have to start from scratch. For example |
| 135 | +when you want to create a symbol called _Comparator_, you can duplicate the |
| 136 | +existing _OpAmp_ symbol, rename it to _Comparator_, adjust its metadata, |
| 137 | +graphics and pins as desired, and save it. The result will be a new, |
| 138 | +independent _Comparator_ symbol which has no relation to _OpAmp_ anymore. |
| 139 | +All UUIDs are re-generated, so it is like a new symbol created manually |
| 140 | +from scratch. |
| 141 | ++ |
| 142 | +[NOTE] |
| 143 | +==== |
| 144 | +Usually, this is the operation you are looking for. |
| 145 | +==== |
| 146 | + |
| 147 | +[#breaking-changes] |
| 148 | +== Breaking Changes |
| 149 | + |
| 150 | +As you may understand by now, the data structures of libraries and projects are |
| 151 | +full of references. A project consists of hundreds or thousands of wires, |
| 152 | +traces, nets, pins and pads which are all linked together by referencing |
| 153 | +each other. This is true for every EDA tool, no matter if references are |
| 154 | +made by names, UUIDs or anything else. References are everywhere. |
| 155 | + |
| 156 | +Given this fact, it is also clear that there is always the risk of _broken_ |
| 157 | +references. Imagine you add a symbol to a schematic and connect wires to |
| 158 | +its pins. Now you realize the symbol is not exactly correct as it has |
| 159 | +a pin which the real part doesn't have. So you open the symbol in the library |
| 160 | +editor, delete that pin, and save the symbol. Then you update the project's |
| 161 | +library (with the _Project Library Manager_ in LibrePCB) to update the symbol |
| 162 | +in your schematic with the new one. But you have already attached a wire to |
| 163 | +the pin which no longer exists. This means that the wire holds a reference |
| 164 | +to a pin that doesn't exist (anymore), a case which we call _broken reference_. |
| 165 | + |
| 166 | +Some tools may silently ignore such broken references and try to revert to a |
| 167 | +valid state. In this particular case, they might silently disconnect the wire |
| 168 | +from the pin, leaving behind a "dead end" wire. |
| 169 | + |
| 170 | +Other tools, like LibrePCB, are more strict about broken references. Instead |
| 171 | +of silently ignoring such (potentially unintended, dangerous) invalid |
| 172 | +situations, the tool throws an error to inform you about the problem. This |
| 173 | +may lead to a situation where you cannot open the project anymore until the |
| 174 | +problem is fixed (e.g. the deletion of the pin is reverted). |
| 175 | + |
| 176 | +**To avoid headaches and wasted time, such situation should be avoided to |
| 177 | +happen at all.** In other words, it is highly recommended to never make |
| 178 | +so-called _breaking changes_ to existing library elements. If you have a |
| 179 | +situation like the described superfluous symbol pin, it is better to create |
| 180 | +a new library element (using the _Duplicate_ operation) and make the breaking |
| 181 | +changes there. Then just replace the wrong symbol in the schematics with the |
| 182 | +new one. Using this workflow, there will never be any broken references, |
| 183 | +causing no errors or other troubles. |
| 184 | + |
| 185 | +== Making Breaking Changes |
| 186 | + |
| 187 | +LibrePCB tries to prevent you from (accidentally) making breaking changes. |
| 188 | +Generally you don't need to worry about breaking changes in library elements |
| 189 | +-- whenever you made a breaking change to an existing library element, LibrePCB |
| 190 | +will warn you with this banner: |
| 191 | + |
| 192 | +image::breaking-changes-banner.png[alt="Breaking changes banner"] |
| 193 | + |
| 194 | +As soon as this red banner shows up, **the editor is put into read-only mode |
| 195 | +and saving is not possible anymore**. Now you have three options: |
| 196 | + |
| 197 | +Undo:: |
| 198 | +If the breaking change was not intended, you can just undo the change |
| 199 | +(kbd:[Ctrl+Z]) and the editor will leave the read-only mode automatically. |
| 200 | + |
| 201 | +Duplicate:: |
| 202 | +If you instead want to make the change in a new library element rather than |
| 203 | +breaking the opened element (as described/recommended in the |
| 204 | +<<duplicate,Duplicate>> section above), just click the menu:Duplicate[] |
| 205 | +button in the banner and make the changes in the newly opened tab. LibrePCB |
| 206 | +will then automatically undo the breaking changes in the existing library |
| 207 | +element to leave the read-only mode. |
| 208 | + |
| 209 | +Unlock:: |
| 210 | +The third option is the only dangerous one -- by pressing & holding the |
| 211 | +menu:Unlock[] button you can leave the read-only mode, so it will be possible |
| 212 | +to actually save the breaking changes to disk. |
| 213 | ++ |
| 214 | +[IMPORTANT] |
| 215 | +==== |
| 216 | +This operation is regularly the reason why inexperienced LibrePCB users end |
| 217 | +up in troubles and ask us for help, complain about errors, or even blaming us |
| 218 | +about bugs in the libraries or the tool -- bugs which don't exist! |
| 219 | +
|
| 220 | +So: **Only use the unlock feature if you have fully understood how our |
| 221 | +referencing system works, what breaking changes are, and what consequences |
| 222 | +they have.** |
| 223 | +
|
| 224 | +Simply put, there is only one case where it is safe to unlock and make |
| 225 | +breaking changes to an existing library element: **If that particular library |
| 226 | +element is not referenced yet from anywhere else.** For example a symbol is |
| 227 | +not referenced from anywhere else if it has never been loaded as a gate into |
| 228 | +a component. If you create a component using that particular symbol, the symbol |
| 229 | +is considered as referenced -- even though you never added it to a project. |
| 230 | +==== |
| 231 | ++ |
| 232 | +A typical case for using the unlock feature is to continue work on an |
| 233 | +unfinished library element. For example you started to create a new symbol |
| 234 | +today, but you have to shut down the computer before it is finished. Tomorrow |
| 235 | +you open the symbol again to continue working on it. In this case, LibrePCB |
| 236 | +will prevent you from making breaking changes, and you have to unlock it to |
| 237 | +continue work. It wouldn't be reasonable in this case to duplicate the |
| 238 | +unfinished library element -- just unlock it. |
| 239 | ++ |
| 240 | +[TIP] |
| 241 | +==== |
| 242 | +For unlocking, you need to press and hold the button for a moment. The required |
| 243 | +holding time depends on the age of the library element to unlock. For the |
| 244 | +typical use-case of continuing work on a library element you just created the |
| 245 | +day before, only a short hold time is needed. But to unlock a library |
| 246 | +element that has existed for a year, you need to hold the unlock button for |
| 247 | +several seconds because the older the library element is, the higher the |
| 248 | +probability that it has already been referenced from other objects, and |
| 249 | +therefore the higher the risk of troubles. |
| 250 | +
|
| 251 | +**So if a library element needs a long time to unlock, you should think twice |
| 252 | +about if you are really sure to make breaking changes to it.** |
| 253 | +==== |
| 254 | + |
| 255 | +== Recommendations |
| 256 | + |
| 257 | +Here are some simple recommendations which help to avoid running into troubles |
| 258 | +due to broken references: |
| 259 | + |
| 260 | +* **Never copy/move/modify files on the file system directly.** Always perform |
| 261 | + operations in LibrePCB, as LibrePCB will take care of UUID handling then. |
| 262 | + As soon as you edit files on the file system directly, there is no safety |
| 263 | + net anymore and you can run easily into a hell of a mess. |
| 264 | +* When creating new library elements by copying an existing library element, |
| 265 | + **use the _duplicate_ operation, not the _copy_ operation**. Generally, |
| 266 | + the _copy_ operation is almost never what you are looking for. |
| 267 | +* When the "breaking changes"-banner shows up in the library editor, **do not |
| 268 | + click on menu:Unlock[] unless you are 100% sure that the library element |
| 269 | + has not been used by another library element or a project yet.** If you |
| 270 | + are not 100% sure about this, use the _Duplicate_ operation. |
0 commit comments