├── .gitignore ├── LICENSE ├── README.md └── Makefile /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /src/ 3 | /bin/ 4 | /doc/ 5 | /target/ 6 | /examples/ 7 | /.rust 8 | rusti.sh 9 | .travis.yml 10 | cargo-lite.conf 11 | .symlink-info 12 | *.swp 13 | 14 | Cargo.toml 15 | 16 | watch.sh 17 | 18 | build.sh 19 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Sven Nilsen 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Rust-Empty 2 | ========== 3 | 4 | *Notice: Rust-Empty is deprecated and replaced by Cargo, which comes with Rust* 5 | 6 | A Makefile to get started with Rust development. 7 | MIT license (or just use it as you like). 8 | Requires Linux or Mac OS X (with developer tools). 9 | Experimental support for Mingw on Windows. 10 | 11 | If you want to contact me, I often hang around in the #rust IRC channel (bvssvni) 12 | 13 | It is recommended to install [Cargo](https://github.com/rust-lang/cargo) 14 | Cargo will replace a subset of the features of Rust-Empty over time. 15 | 16 | ##Example 1: Hello World 17 | 18 | 1. Copy [Makefile](https://raw.githubusercontent.com/bvssvni/rust-empty/master/Makefile) to a new empty project folder. 19 | 2. Open the Terminal and navigate to the project folder. 20 | 3. `make nightly-install` 21 | 4. `make run` to create and run "hello world" 22 | 23 | The "hello world" example is created when there is no `src/main.rs`. 24 | 25 | ##Example 2: New open source library 26 | 27 | 1. Create new repository on Github. 28 | 3. `git clone ` 29 | 4. Copy `Makefile` to the folder. 30 | 5. `make git-ignore` 31 | 6. `make lib` 32 | 7. Change `DEFAULT = help` to `DEFAULT = lib` 33 | 34 | ##Example 3: Compile library on file changes 35 | 36 | 1. Assuming you have set up the library and set the `DEFAULT` parameter properly 37 | 2. `make watch` to generate the watch script 38 | 3. `./watch.sh` 39 | 4. Edit the source and save to do compilation 40 | 41 | ##Example 4: Compile and run application on file changes 42 | 43 | 1. Assuming you have set up the application properly 44 | 2. `make watch` to generate the watch script 45 | 3. `./watch.sh src "make run"` 46 | 4. Edit the source and save to compile and run the application 47 | 48 | This technique can be applied to running unit tests and benchmarks as well. 49 | To chain commands, use the `&&` operator, for example `./watch.sh src "make test-internal && bench-internal"`. 50 | 51 | ##Example 5: Compile example with conditional compilation 52 | 53 | 1. Assume you have an example 'examples/hello.rs' 54 | 2. Put `#[cfg(foo)]` in 'hello.rs' where you want conditional compilation 55 | 3. Type `make examples/hello.rs COMPILER_FLAGS+="--cfg foo"` 56 | 57 | The 'foo' part can be switched with any other flag. 58 | You can also have multiple flags and require more than one by using `#[cfg(foo, bar)]`. 59 | Type `make examples/hello.rs COMPILER_FLAGS+="--cfg foo --cfg bar"` to activate both. 60 | 61 | ##What is Rust-Empty? 62 | 63 | Rust-Empty is a user friendly Makefile/Bash setup tool for Rust programmers. 64 | It automates setup of directories and configuration files. 65 | Once setup is completed, replace or modify the Makefile to suit your needs. 66 | The Makefile works out of the box on Linux and OSX (with developer tools). 67 | The setup uses best practices and conventions learned from the Rust community. 68 | Pull requests/fixes are welcome! 69 | 70 | *Latest feature: Build symlink dependencies!* 71 | 72 | What are these 'best practices'? 73 | 74 | For example: 75 | 76 | * Put code in a `src/` directory 77 | * Add a `crate_id` attribute for your library 78 | * Deny missing doc attribute for library 79 | * A `.gitignore` to keep repository clean 80 | * Library dependencies should be in `target/deps` directory 81 | * Example programs better not be in the `src/` directory 82 | * Need a `-O` flag to compile optimized code 83 | * Dependencies, rust-nightly check through Travis CI etc. 84 | 85 | ###Goals 86 | 87 | * Work on Linux, Mac OS X and Mingw on Windows 88 | * Convention by 'best practice' of Rust community 89 | * Features are optional, non-interfering and gives informative output 90 | * Integrate with other tools from Rust community 91 | 92 | ###Non-Goals 93 | 94 | * Replace Cargo, the Rust package manager 95 | * Backward compatibility 96 | * Require any sort of internal configuration 97 | 98 | ##Usage 99 | 100 | 1. Create a new empty folder for your project. 101 | 2. Copy 'Makefile' to the project folder. 102 | 3. Open the Terminal window and navigate to the project folder. 103 | 4. Type 'make help'. 104 | 105 | ``` 106 | --- rust-empty (0.7 000) 107 | make run - Runs executable 108 | make exe - Builds main executable 109 | make lib - Both static and dynamic library 110 | make rlib - Static library 111 | make dylib - Dynamic library 112 | make test - Tests library internally and externally 113 | make test-internal - Tests library internally 114 | make test-external - Tests library externally 115 | make bench - Benchmarks library internally and externally 116 | make bench-internal - Benchmarks library internally 117 | make bench-external - Benchmarks library externally 118 | make doc - Builds documentation for library 119 | make git-ignore - Setup files to be ignored by Git 120 | make examples - Builds examples 121 | make cargo-exe - Setup executable package 122 | make cargo-lib - Setup library package 123 | make rust-ci-lib - Setup Travis CI Rust library 124 | make rust-ci-exe - Setup Travis CI Rust executable 125 | make rusti - Setup 'rusti.sh' for interactive Rust 126 | make watch - Setup 'watch.sh' for compilation on save 127 | make loc - Count lines of code in src folder 128 | make nightly-install - Installs Rust nightly build 129 | make nightly-uninstall - Uninstalls Rust nightly build 130 | make clean - Deletes binaries and documentation. 131 | make clear-project - WARNING: Deletes project files except 'Makefile' 132 | make clear-git - WARNING: Deletes Git setup 133 | make symlink-build - Creates a script for building dependencies 134 | make symlink-info - Symlinked libraries dependency info 135 | make target-dir - Creates directory for current target 136 | ``` 137 | 138 | All the commands creates the files and folders necessary to compile. 139 | For example, if you type `make exe` it will add a hello-world program to `src/main.rs`. 140 | You can use `make clear-project` to revert back to just the 'Makefile'. 141 | 142 | ##Unit Testing & Benchmarking 143 | 144 | Internal unit tests and benchmarks are located in the same source as the library, `src/lib.rs`. 145 | External unit tests and benchmarks are located in `src/test.rs`. 146 | 147 | ##Linking to Libraries 148 | 149 | The directory `target/deps/` is linked by default. If you put Rust libraries in this directory it will link statically if there is an ".rlib" file or dynamically if ".dylib" (OSX), ".so" (Linux) or ".dll" (Window). 150 | 151 | ##Symlinked Libraries 152 | 153 | A symlink is a file that points to another file. 154 | Symlinks are useful when working across multiple repositories and testing integration. 155 | 156 | Using the command `ln -s `, you can link the output file from another project to the `target/deps/` folder. 157 | 158 | The command `make symlink-info` creates a file `.symlink-info` that contains the file name, current commit, the remote origin url and which remote branches this commit is available. For more information about how to read '.symlink-info' files, see https://github.com/bvssvni/rust-empty/issues/114 159 | 160 | NOTICE: The `ln -s ` for relative file names does not work on OSX. Use absolute file names instead. For example `ln -s /Users/myser/Desktop/mylibrary/target/x86_64-apple-darwin/lib/mylib.rlib target/x86_64-apple-darwin/mylib.rlib`. See https://github.com/bvssvni/rust-empty/issues/100 161 | 162 | The command `make symlink-build` creates a file `build.sh` that can build projects by symlinks. 163 | You can type `./build.sh` to build just the project, or `./build.sh deps` to build everything. 164 | 165 | ##Introduction To Rust 166 | 167 | Rust is a programming language developed at Mozilla Research. 168 | 169 | Rust nightly builds 170 | Rust at wikipedia 171 | Official web page 172 | Documentation at Github wiki 173 | Rust at Reddit 174 | Rust IRC channel 175 | Editor syntax highlighting 176 | Rust packages 177 | 178 | ###For those new to terminal/Github: 179 | 180 | How to use the terminal 181 | How to use Vim 182 | How to use Github 183 | 184 | ###Rust CI 185 | 186 | Each night the latest version of Rust on Ubuntu is built against a list of projects. 187 | Add project by following instructions on the site: 188 | 189 | Rust CI 190 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Rust-Empty: A Makefile to get started with Rust 2 | # https://github.com/bvssvni/rust-empty 3 | # 4 | # The MIT License (MIT) 5 | # 6 | # Copyright (c) 2014 Sven Nilsen 7 | # 8 | # Permission is hereby granted, free of charge, to any person obtaining a copy of 9 | # this software and associated documentation files (the "Software"), to deal in 10 | # the Software without restriction, including without limitation the rights to 11 | # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 12 | # the Software, and to permit persons to whom the Software is furnished to do so, 13 | # subject to the following conditions: 14 | # 15 | # The above copyright notice and this permission notice shall be included in all 16 | # copies or substantial portions of the Software. 17 | # 18 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 20 | # FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 21 | # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 22 | # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 | # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | 25 | SHELL := /bin/bash 26 | 27 | # The default make command. 28 | # Change this to 'lib' if you are building a library. 29 | DEFAULT = help 30 | # The entry file of library source. 31 | # Change this to support multi-crate source structure. 32 | # For advanced usage, you can rename the file 'rust-empty.mk' 33 | # and call it with 'make -f rust-empty.mk ' from your Makefile. 34 | LIB_ENTRY_FILE = src/lib.rs 35 | # The entry file of executable source. 36 | EXE_ENTRY_FILE = src/main.rs 37 | 38 | EXAMPLE_FILES = examples/*.rs 39 | SOURCE_FILES = $(shell test -e src/ && find src -type f) 40 | 41 | COMPILER = rustc 42 | 43 | # For release: 44 | COMPILER_FLAGS = -O 45 | # For debugging: 46 | # COMPILER_FLAGS = -g 47 | 48 | RUSTDOC = rustdoc 49 | 50 | # Extracts target from rustc. 51 | TARGET = $(shell rustc --version --verbose 2> /dev/null | awk "/host:/ { print \$$2 }") 52 | # TARGET = x86_64-unknown-linux-gnu 53 | # TARGET = x86_64-apple-darwin 54 | 55 | TARGET_LIB_DIR = target/deps/ 56 | 57 | EXE_FILE = $(shell (rustc --crate-type=bin --print-file-name "$(EXE_ENTRY_FILE)" 2> /dev/null) || (echo "main")) 58 | EXE_DIR = bin 59 | EXE = $(EXE_DIR)/$(EXE_FILE) 60 | 61 | # Use 'VERBOSE=1' to echo all commands, for example 'make help VERBOSE=1'. 62 | ifdef VERBOSE 63 | Q := 64 | else 65 | Q := @ 66 | endif 67 | 68 | all: $(DEFAULT) 69 | 70 | help: 71 | $(Q)echo "--- rust-empty (0.7 005)" 72 | $(Q)echo "make run - Runs executable" 73 | $(Q)echo "make exe - Builds main executable" 74 | $(Q)echo "make lib - Builds library" 75 | $(Q)echo "make test - Tests library internally and externally" 76 | $(Q)echo "make test-internal - Tests library internally" 77 | $(Q)echo "make test-external - Tests library externally" 78 | $(Q)echo "make bench - Benchmarks library internally and externally" 79 | $(Q)echo "make bench-internal - Benchmarks library internally" 80 | $(Q)echo "make bench-external - Benchmarks library externally" 81 | $(Q)echo "make doc - Builds documentation for library" 82 | $(Q)echo "make git-ignore - Setup files to be ignored by Git" 83 | $(Q)echo "make examples - Builds examples" 84 | $(Q)echo "make cargo-exe - Setup executable package" 85 | $(Q)echo "make cargo-lib - Setup library package" 86 | $(Q)echo "make rust-ci-lib - Setup Travis CI Rust library" 87 | $(Q)echo "make rust-ci-exe - Setup Travis CI Rust executable" 88 | $(Q)echo "make rusti - Setup 'rusti.sh' for interactive Rust" 89 | $(Q)echo "make watch - Setup 'watch.sh' for compilation on save" 90 | $(Q)echo "make loc - Count lines of code in src folder" 91 | $(Q)echo "make nightly-install - Installs Rust nightly build" 92 | $(Q)echo "make nightly-uninstall - Uninstalls Rust nightly build" 93 | $(Q)echo "make clean - Deletes binaries and documentation." 94 | $(Q)echo "make clear-project - WARNING: Deletes project files except 'Makefile'" 95 | $(Q)echo "make clear-git - WARNING: Deletes Git setup" 96 | $(Q)echo "make symlink-build - Creates a script for building dependencies" 97 | $(Q)echo "make symlink-info - Symlinked libraries dependency info" 98 | $(Q)echo "make target-dir - Creates directory for current target" 99 | 100 | .PHONY: \ 101 | bench \ 102 | bench-internal \ 103 | bench-external \ 104 | cargo-lib \ 105 | cargo-exe \ 106 | clean \ 107 | clear-git \ 108 | clear-project \ 109 | loc \ 110 | nightly-install \ 111 | nightly-uninstall \ 112 | run \ 113 | rusti \ 114 | rust-ci-lib \ 115 | rust-ci-exe \ 116 | symlink-build \ 117 | symlink-info \ 118 | target-dir \ 119 | test \ 120 | test-internal \ 121 | test-external \ 122 | watch 123 | 124 | nightly-install: 125 | $(Q)cd ~ \ 126 | && curl -s https://static.rust-lang.org/rustup.sh > rustup.sh \ 127 | && ( \ 128 | echo "Rust install-script stored as '~/rustup.sh'" ; \ 129 | read -p "Do you want to install? [y/n]:" -n 1 -r ; \ 130 | echo "" ; \ 131 | if [[ $$REPLY =~ ^[Yy]$$ ]] ; \ 132 | then \ 133 | cat rustup.sh | sudo sh -s -- --channel=nightly; \ 134 | fi \ 135 | ) 136 | 137 | nightly-uninstall: 138 | $(Q)cd ~ \ 139 | && curl -s https://static.rust-lang.org/rustup.sh > rustup.sh \ 140 | && ( \ 141 | echo "Rust install-script stored as '~/rustup.sh'" ; \ 142 | read -p "Do you want to uninstall? [y/n]:" -n 1 -r ; \ 143 | echo "" ; \ 144 | if [[ $$REPLY =~ ^[Yy]$$ ]] ; \ 145 | then \ 146 | cat rustup.sh | sudo sh -s -- --uninstall ; \ 147 | fi \ 148 | ) 149 | 150 | cargo-exe: $(EXE_ENTRY_FILE) 151 | $(Q)( \ 152 | test -e Cargo.toml \ 153 | && echo "--- The file 'Cargo.toml' already exists" \ 154 | ) \ 155 | || \ 156 | ( \ 157 | name=$${PWD##/*/} ; \ 158 | echo -e "[package]\n\nname = \"$$name\"\nversion = \"0.0.0\"\nauthors = [\"Your Name \"]\ntags = []\n\n[[bin]]\n\nname = \"$$name\"\npath = \"$(EXE_ENTRY_FILE)\"\n" > Cargo.toml \ 159 | && echo "--- Created 'Cargo.toml' for executable" \ 160 | && cat Cargo.toml \ 161 | ) 162 | 163 | cargo-lib: $(LIB_ENTRY_FILE) 164 | $(Q)( \ 165 | test -e Cargo.toml \ 166 | && echo "--- The file 'Cargo.toml' already exists" \ 167 | ) \ 168 | || \ 169 | ( \ 170 | name=$${PWD##/*/} ; \ 171 | echo -e "[package]\n\nname = \"$$name\"\nversion = \"0.0.0\"\nauthors = [\"Your Name \"]\ntags = []\n\n[lib]\n\nname = \"$$name\"\npath = \"$(LIB_ENTRY_FILE)\"\n" > Cargo.toml \ 172 | && echo "--- Created 'Cargo.toml' for library" \ 173 | && cat Cargo.toml \ 174 | ) 175 | 176 | rust-ci-lib: $(LIB_ENTRY_FILE) 177 | $(Q)( \ 178 | test -e .travis.yml \ 179 | && echo "--- The file '.travis.yml' already exists" \ 180 | ) \ 181 | || \ 182 | ( \ 183 | echo -e "install:\n - wget http://static.rust-lang.org/dist/rust-nightly-x86_64-unknown-linux-gnu.tar.gz -O - | sudo tar zxf - --strip-components 1 -C /usr/local\nscript:\n - make lib\n" > .travis.yml \ 184 | && echo "--- Created '.travis.yml' for library" \ 185 | && cat .travis.yml \ 186 | ) 187 | 188 | rust-ci-exe: $(EXE_ENTRY_FILE) 189 | $(Q)( \ 190 | test -e .travis.yml \ 191 | && echo "--- The file '.travis.yml' already exists" \ 192 | ) \ 193 | || \ 194 | ( \ 195 | echo -e "install:\n - wget http://static.rust-lang.org/dist/rust-nightly-x86_64-unknown-linux-gnu.tar.gz -O - | sudo tar zxf - --strip-components 1 -C /usr/local\nscript:\n - make exe\n" > .travis.yml \ 196 | && echo "--- Created '.travis.yml' for executable" \ 197 | && cat .travis.yml \ 198 | ) 199 | 200 | doc: $(SOURCE_FILES) | src/ 201 | $(Q)$(RUSTDOC) $(LIB_ENTRY_FILE) -L "$(TARGET_LIB_DIR)" \ 202 | && echo "--- Built documentation" 203 | 204 | run: exe 205 | $(Q)cd "$(EXE_DIR)/" \ 206 | && ./$(EXE_FILE) 207 | 208 | target-dir: $(TARGET_LIB_DIR) 209 | 210 | exe: $(EXE) | $(TARGET_LIB_DIR) 211 | 212 | $(EXE): $(SOURCE_FILES) | $(EXE_DIR)/ $(EXE_ENTRY_FILE) 213 | $(Q)$(COMPILER) --target "$(TARGET)" $(COMPILER_FLAGS) $(EXE_ENTRY_FILE) -o $(EXE) -L "$(TARGET_LIB_DIR)" -L "target" \ 214 | && echo "--- Built executable" \ 215 | && echo "--- Type 'make run' to run executable" 216 | 217 | test: test-internal test-external 218 | $(Q)echo "--- Internal tests succeeded" \ 219 | && echo "--- External tests succeeded" 220 | 221 | test-external: $(EXE_DIR)/test-external 222 | $(Q)cd "$(EXE_DIR)/" \ 223 | && ./test-external 224 | 225 | $(EXE_DIR)/test-external: $(SOURCE_FILES) | lib $(EXE_DIR)/ src/test.rs 226 | $(Q)$(COMPILER) --target "$(TARGET)" $(COMPILER_FLAGS) --test src/test.rs -o "$(EXE_DIR)/test-external" -L "$(TARGET_LIB_DIR)" -L "target" \ 227 | && echo "--- Built external test runner" 228 | 229 | test-internal: $(EXE_DIR)/test-internal 230 | $(Q)cd "$(EXE_DIR)/" \ 231 | && ./test-internal 232 | 233 | $(EXE_DIR)/test-internal: $(SOURCE_FILES) | lib src/ $(EXE_DIR)/ 234 | $(Q)$(COMPILER) --target "$(TARGET)" $(COMPILER_FLAGS) --test $(LIB_ENTRY_FILE) -o "$(EXE_DIR)/test-internal" -L "$(TARGET_LIB_DIR)" -L "target" \ 235 | && echo "--- Built internal test runner" 236 | 237 | bench: bench-internal bench-external 238 | 239 | bench-external: test-external 240 | $(Q)$(EXE_DIR)/test-external --bench 241 | 242 | bench-internal: test-internal 243 | $(Q)$(EXE_DIR)/test-internal --bench 244 | 245 | lib: 246 | $(Q)( \ 247 | cargo build \ 248 | && echo "--- Type 'make test' to test library" \ 249 | ) \ 250 | || \ 251 | ( \ 252 | echo "--- Type 'make cargo-lib' to create Cargo.toml" \ 253 | ) 254 | 255 | $(EXE_DIR)/: 256 | $(Q)mkdir -p $(EXE_DIR) 257 | 258 | $(TARGET_LIB_DIR)/: 259 | $(Q)mkdir -p $(TARGET_LIB_DIR) 260 | 261 | src/: 262 | $(Q)mkdir -p src 263 | 264 | examples-dir: 265 | $(Q)test -e examples \ 266 | || \ 267 | ( \ 268 | mkdir examples \ 269 | && echo -e "fn main() {\n\tprintln!(\"Hello!\");\n}\n" > examples/hello.rs \ 270 | && echo "--- Created examples folder" \ 271 | ) 272 | 273 | rust-dir: 274 | $(Q)mkdir -p .rust 275 | 276 | git-ignore: 277 | $(Q)( \ 278 | test -e .gitignore \ 279 | && echo "--- The file '.gitignore' already exists" \ 280 | ) \ 281 | || \ 282 | ( \ 283 | echo -e ".DS_Store\n*~\n*#\n*.o\n*.so\n*.swp\n*.old\n*.bak\n*.kate-swp\n*.dylib\n*.dSYM\n*.dll\n*.rlib\n*.dummy\n*.exe\n*-test\n/$(EXE)\n/$(EXE_DIR)/test-internal\n/$(EXE_DIR)/test-external\n/doc/\n/target/\n/build/\n/.rust/\nrusti.sh\nwatch.sh\n/examples/**\n!/examples/*.rs\n!/examples/assets/\n!/$(EXE_DIR)/assets/" > .gitignore \ 284 | && echo "--- Created '.gitignore' for git" \ 285 | && cat .gitignore \ 286 | ) 287 | 288 | examples: $(EXAMPLE_FILES) 289 | 290 | $(EXAMPLE_FILES): lib examples-dir 291 | $(Q)$(COMPILER) --target "$(TARGET)" $(COMPILER_FLAGS) $@ -L "$(TARGET_LIB_DIR)" -L "target" --out-dir examples/ \ 292 | && echo "--- Built '$@' (make $@)" 293 | 294 | $(EXE_ENTRY_FILE): | src/ 295 | $(Q)test -e $(EXE_ENTRY_FILE) \ 296 | || \ 297 | ( \ 298 | name=$${PWD##/*/} ; \ 299 | echo -e "#![crate_name = \"$$name\"]\n\nfn main() {\n\tprintln!(\"Hello world!\");\n}" > $(EXE_ENTRY_FILE) \ 300 | ) 301 | 302 | src/test.rs: | src/ 303 | $(Q)test -e src/test.rs \ 304 | || \ 305 | ( \ 306 | touch src/test.rs \ 307 | ) 308 | 309 | $(LIB_ENTRY_FILE): | src/ 310 | $(Q)test -e $(LIB_ENTRY_FILE) \ 311 | || \ 312 | ( \ 313 | name=$${PWD##/*/} ; \ 314 | echo -e "#![crate_name = \"$$name\"]\n#![deny(missing_doc)]\n\n//! Documentation goes here.\n" > $(LIB_ENTRY_FILE) \ 315 | ) 316 | 317 | clean: 318 | $(Q)cargo clean 319 | $(Q)rm -rf "doc/" 320 | $(Q)rm -f "$(EXE)" 321 | $(Q)rm -f "$(EXE_DIR)/test-internal" 322 | $(Q)rm -f "$(EXE_DIR)/test-external" 323 | $(Q)echo "--- Deleted binaries and documentation" 324 | 325 | clear-project: 326 | $(Q)rm -f ".symlink-info" 327 | $(Q)rm -f "Cargo.toml" 328 | $(Q)rm -f "Cargo.lock" 329 | $(Q)rm -f ".travis.yml" 330 | $(Q)rm -f "rusti.sh" 331 | $(Q)rm -f "watch.sh" 332 | $(Q)rm -rf "target/" 333 | $(Q)rm -rf "src/" 334 | $(Q)rm -rf "$(EXE_DIR)/" 335 | $(Q)rm -rf "examples/" 336 | $(Q)rm -rf "doc/" 337 | $(Q)echo "--- Removed all source files, binaries and documentation" \ 338 | && echo "--- Content in project folder" \ 339 | && ls -a 340 | 341 | clear-git: 342 | $(Q)rm -f ".gitignore" 343 | $(Q)rm -rf ".git" 344 | $(Q)echo "--- Removed Git" \ 345 | && echo "--- Content in project folder" \ 346 | && ls -a 347 | 348 | # borrowed from http://stackoverflow.com/q/649246/1256624 349 | define RUSTI_SCRIPT 350 | #!/bin/bash 351 | 352 | #written by mcpherrin 353 | 354 | while true; do 355 | echo -n "> " 356 | read line 357 | TMP="`mktemp r.XXXXXX`" 358 | $(COMPILER) - -o $$TMP -L "$(TARGET_LIB_DIR)" < rusti.sh \ 407 | && chmod +x rusti.sh \ 408 | && echo "--- Created 'rusti.sh'" \ 409 | && echo "--- Type './rusti.sh' to start interactive Rust" \ 410 | ) 411 | 412 | # borrowed from http://stackoverflow.com/q/649246/1256624 413 | define WATCH_SCRIPT 414 | #!/bin/bash 415 | 416 | #written by zzmp 417 | 418 | # This script will recompile a rust project using `make` 419 | # every time something in the specified directory changes. 420 | 421 | # Watch files in infinite loop 422 | watch () { 423 | UNAME=$$(uname) 424 | if [ -e "$$2" ]; then 425 | echo "Watching files in $$2.." 426 | CTIME=$$(date "+%s") 427 | while :; do 428 | sleep 1 429 | for f in `find $$2 -type f -name "*.rs"`; do 430 | if [[ $$UNAME == "Darwin" ]]; then 431 | st_mtime=$$(stat -f "%m" "$$f") 432 | elif [[ $$UNAME == "FreeBSD" ]]; then 433 | st_mtime=$$(stat -f "%m" "$$f") 434 | else 435 | st_mtime=$$(stat -c "%Y" "$$f") 436 | fi 437 | if [ $$st_mtime -gt $$CTIME ]; then 438 | CTIME=$$(date "+%s") 439 | echo "~~~ Rebuilding" 440 | $$1 441 | if [ ! $$? -eq 0 ]; then 442 | echo "" 443 | fi 444 | fi 445 | done 446 | done 447 | else 448 | echo "$$2 is not a valid directory" 449 | fi 450 | } 451 | 452 | # Capture user input with defaults 453 | CMD=$${1:-make} 454 | DIR=$${2:-src} 455 | 456 | if [ $${CMD:0:2} = '-h' ]; then 457 | echo ' 458 | This script will recompile a rust project using `make` 459 | every time something in the specified directory changes. 460 | 461 | Use: ./watch.sh [CMD] [DIR] 462 | Example: ./watch.sh "make run" src 463 | 464 | CMD: Command to execute 465 | Complex commands may be passed as strings 466 | `make` by default 467 | DIR: Directory to watch 468 | src by default 469 | 470 | If DIR is supplied, CMD must be as well.\n' 471 | else 472 | watch "$$CMD" "$$DIR" 473 | fi 474 | 475 | endef 476 | export WATCH_SCRIPT 477 | 478 | watch: $(TARGET_LIB_DIR) 479 | $(Q)( \ 480 | test -e watch.sh \ 481 | && echo "--- The file 'watch.sh' already exists" \ 482 | ) \ 483 | || \ 484 | ( \ 485 | echo -e "$$WATCH_SCRIPT" > watch.sh \ 486 | && chmod +x watch.sh \ 487 | && echo "--- Created 'watch.sh'" \ 488 | && echo "--- Type './watch.sh' to start compilation on save" \ 489 | && echo "--- Type './watch.sh -h' for more options" \ 490 | ) 491 | 492 | # borrowed from http://stackoverflow.com/q/649246/1256624 493 | define SYMLINK_BUILD_SCRIPT 494 | #!/bin/bash 495 | # written by bvssvni 496 | # Modify the setting to do conditional compilation. 497 | # For example "--cfg my_feature" 498 | SETTINGS="" 499 | # ================================================ 500 | 501 | MAKE=make 502 | if [ "$$OS" == "Windows_NT" ]; then 503 | MAKE=mingw32-make 504 | fi 505 | 506 | # Checks if an item exists in an array. 507 | # Copied from http://stackoverflow.com/questions/3685970/check-if-an-array-contains-a-value 508 | function contains() { 509 | local n=$$# 510 | local value=$${!n} 511 | for ((i=1;i < $$#;i++)) { 512 | if [ "$${!i}" == "$${value}" ]; then 513 | echo "y" 514 | return 0 515 | fi 516 | } 517 | echo "n" 518 | return 1 519 | } 520 | 521 | # This is a counter used to insert dependencies. 522 | # It is global because we need an array of all the 523 | # visited dependencies. 524 | i=0 525 | function build_deps { 526 | local current=$$(pwd) 527 | for symlib in $$(find $(TARGET_LIB_DIR) -type l) ; do 528 | cd $$current 529 | echo $$symlib 530 | local original_file=$$(readlink $$symlib) 531 | local original_dir=$$(dirname $$original_file) 532 | cd $$original_dir 533 | 534 | # Go to the git root directory. 535 | local current_git_dir=$$(git rev-parse --show-toplevel) 536 | echo "--- Parent $$current" 537 | echo "--- Child $$current_git_dir" 538 | cd $$current_git_dir 539 | 540 | # Skip building if it is already built. 541 | if [ $$(contains "$${git_dir[@]}" $$current_git_dir) == "y" ]; then 542 | echo "--- Visited $$current_git_dir" 543 | continue 544 | fi 545 | 546 | # Remember git directory to not build it twice 547 | git_dir[i]=$$current_git_dir 548 | let i+=1 549 | 550 | # Visit the symlinks and build the dependencies 551 | build_deps 552 | 553 | echo "--- Building $$current_git_dir" \ 554 | 555 | # First check for a 'build.sh' script with default settings. 556 | # Check for additional 'rust-empty.mk' file. \ 557 | # Compile with the settings flags. \ 558 | # If no other options, build with make. 559 | ( \ 560 | test -e build.sh \ 561 | && ./build.sh \ 562 | ) \ 563 | || \ 564 | ( \ 565 | test -e rust-empty.mk \ 566 | && $$MAKE -f rust-empty.mk clean \ 567 | && $$MAKE -f rust-empty.mk \ 568 | ) \ 569 | || \ 570 | ( \ 571 | test -e Makefile \ 572 | && $$MAKE clean \ 573 | && $$MAKE \ 574 | ) \ 575 | || \ 576 | ( \ 577 | test -e Cargo.toml \ 578 | && cargo build \ 579 | ) \ 580 | || \ 581 | ( \ 582 | echo "--- ERROR: Missing Makefile in $$current_git_dir" \ 583 | ) 584 | done 585 | cd $$current 586 | } 587 | 588 | # Mark main project as visited to avoid infinite loop. 589 | git_dir[i]=$$(pwd) 590 | let i+=1 591 | if [ "$$1" == "deps" ]; then 592 | build_deps 593 | fi 594 | 595 | echo "--- Building $$(pwd)" 596 | ( \ 597 | test -e rust-empty.mk \ 598 | && $$MAKE -f rust-empty.mk clean \ 599 | && $$MAKE -f rust-empty.mk COMPILER_FLAGS+="$$SETTINGS" \ 600 | ) \ 601 | || \ 602 | ( \ 603 | $$MAKE clean 604 | $$MAKE COMPILER_FLAGS+="$$SETTINGS" 605 | ) 606 | 607 | endef 608 | export SYMLINK_BUILD_SCRIPT 609 | 610 | symlink-build: 611 | $(Q)( \ 612 | test -e build.sh \ 613 | && echo "--- The file 'build.sh' already exists" \ 614 | ) \ 615 | || \ 616 | ( \ 617 | echo -e "$$SYMLINK_BUILD_SCRIPT" > build.sh \ 618 | && chmod +x build.sh \ 619 | && echo "--- Created 'build.sh'" \ 620 | && echo "--- Type './build.sh deps' to build everything" \ 621 | ) 622 | 623 | loc: 624 | $(Q)echo "--- Counting lines of .rs files in 'src' (LOC):" \ 625 | && find src/ -type f -name "*.rs" -exec cat {} \; | wc -l 626 | 627 | # Finds the original locations of symlinked libraries and 628 | # prints the commit hash with remote branches containing that commit. 629 | symlink-info: 630 | $(Q) current=$$(pwd) ; \ 631 | for symlib in $$(find $(TARGET_LIB_DIR) -type l) ; do \ 632 | cd $$current ; \ 633 | echo $$symlib ; \ 634 | original_file=$$(readlink $$symlib) ; \ 635 | original_dir=$$(dirname $$original_file) ; \ 636 | cd $$original_dir ; \ 637 | commit=$$(git rev-parse HEAD) ; \ 638 | echo $$commit ; \ 639 | echo "origin:" ; \ 640 | git config --get remote.origin.url ; \ 641 | echo "upstream:" ; \ 642 | git config --get remote.upstream.url ; \ 643 | echo "available in remote branches:" ; \ 644 | git branch -r --contains $$commit ; \ 645 | echo "" ; \ 646 | done \ 647 | > .symlink-info \ 648 | && cd $$current \ 649 | && echo "--- Created '.symlink-info'" \ 650 | && cat .symlink-info 651 | --------------------------------------------------------------------------------