After several years of using cmake, I recently tried to figure out how to change all the dynamic links of the C ++ application to static links. I found that I still need to study the usage of cmake and go to the cmake documentation,
Http://www.cmake.org/cmake/help/syntax.html
See this sentence:
In many ways writing a CMakeLists file is like a writing a program in a simple language. Like most languages CMake provides flow control structures to help you along your way. CMake provides three flow control structures:
Next, let's look at the condition statements, loops, and definition processes. A simple script language is used to control cmake to generate makefile.
In the past, cmake helped me, because I was bored with writing makefile. cmake allowed me to design a good directory structure and not implement the directory tree recursive makefile script myself.
But today, for me who are already familiar with the newlisp language, what tools are more powerful than using newlisp to implement scripts? Why do I still use cmake? I don't need to consider cross-platform compilation. I just want to practice C ++ programming on Linux servers. I only use GCC as the compiler. Using newlisp directly to control GCC allows me to directly use GCC to better understand the behavior of the compiler.
In the spirit of not changing the original cmake project, we created several newlisp scripts to implement recursive directory tree, compile files, and finally dynamic or static links.
Now we will introduce how to use it. The directory structure of this cppcms program is:
tree -L 4.├── builder│ ├── build_config.lsp│ ├── compile.lsp│ ├── compile.lsp~│ ├── dlink.lsp│ ├── dlink.lsp~│ ├── g++.lsp│ ├── link.lsp~│ ├── rebuild.lsp│ ├── slink.lsp│ ├── slink.lsp~│ └── tmpl.lsp├── codes│ ├── main│ │ ├── build│ │ ├── CMakeLists.txt│ │ ├── conf.d│ │ │ ├── ca-certs.crt│ │ │ ├── site.crt│ │ │ ├── ssl.key│ │ │ ├── ssl-pwd.key│ │ │ ├── site.conf│ │ │ ├── default.conf_bk│ │ │ ├── example_ssl.conf│ │ │ ├── fastcgi.cml│ │ │ ├── nginx_signing.key│ │ │ ├── server.crt│ │ │ ├── server.csr│ │ │ ├── server.key│ │ │ └── server.key.org│ │ ├── config.js│ │ ├── create_deploy.sh│ │ ├── include│ │ │ ├── bean│ │ │ ├── configuration.h│ │ │ ├── controller│ │ │ ├── display.h│ │ │ ├── displays.h│ │ │ ├── exception│ │ │ ├── group.h│ │ │ ├── groups.h│ │ │ ├── helper│ │ │ ├── module│ │ │ ├── my_application.h│ │ │ ├── response.h│ │ │ ├── service│ │ │ └── web_user.h│ │ ├── install.sh│ │ ├── jscheck│ │ │ ├── pom.xml│ │ │ └── src│ │ ├── proto│ │ │ ├── build.sh│ │ │ ├── input│ │ │ └── output│ │ ├── resources│ │ │ ├── html│ │ │ ├── images│ │ │ ├── plugin│ │ │ ├── script│ │ │ └── style│ │ ├── src│ │ │ ├── bean│ │ │ ├── CMakeLists.txt│ │ │ ├── controller│ │ │ ├── display.cpp│ │ │ ├── displays.cpp│ │ │ ├── group.cpp│ │ │ ├── groups.cpp│ │ │ ├── helper│ │ │ ├── main.cpp│ │ │ ├── module│ │ │ ├── my_application.cpp│ │ │ ├── service│ │ │ ├── view│ │ │ └── web_user.cc│ │ ├── template│ │ │ ├── accounts.tmpl│ │ │ ├── default.tmpl│ │ │ ├── deny.tmpl│ │ │ ├── gprsConfig.tmpl│ │ │ ├── gprsManager.tmpl│ │ │ ├── groupManagement.tmpl│ │ │ ├── home.tmpl│ │ │ ├── login.tmpl│ │ │ ├── log.tmpl│ │ │ ├── message.tmpl│ │ │ ├── register_client.tmpl│ │ │ ├── updatePassword.tmpl│ │ │ └── userTitle.tmpl│ │ └── tool.sh│ └── test└── README
The running mode is to enter the builder directory for execution.
./Rebuild. LSP
First, compile the tmpl template file of cppcms into a C ++ class.
Compile all. CC and. cpp files into. O files.
Finally, it dynamically links to executable programs.
First look at the rebuild. LSP code:
#!/usr/bin/newlisp ;; init(load "/opt/build_config.lsp")(set 'armory-folder (env "NEWLISP_ARMORY_HOME"))(println (append "newlisp armory home folder: " armory-folder))(load (append armory-folder "/codes/file/file.lsp"))(file:init);; clean files genereated by CMake(set 'cmake-build-dir "../codes/main/build")(file:clean-folder cmake-build-dir);; clean view/*.cpp files generated from cppcms_tmpl_cc(set 'view-dir "../codes/main/src/view")(file:clean-folder view-dir)(set 'tmpl-dir "../codes/main/template");; generate .cc files in view folder(load "tmpl.lsp")(tmpl-to-cc tmpl-dir view-dir);; compile all c++ files to .o file in ./o folder(load "g++.lsp")(set 'include-paths (list "../codes/main/include" "../codes/main/src/../../loki-0.1.7/include"))(set 'o-dir "./o")(set 'src-paths (list "../codes/main/src" "../codes/main/src/bean" "../codes/main/src/controller" "../codes/main/src/helper" "../codes/main/src/module" "../codes/main/src/service" "../codes/main/src/view" ))(compile include-paths src-paths o-dir);; link all .o files(set 'libs (list "pthread" "cppcms" "mongoclient" "booster" "loki" "cryptopp" "boost_system" "boost_thread" "boost_filesystem" ))(set 'binary-name "sports_lottery")(set 'bin-dir "bin")(dynamic-link o-dir bin-dir binary-name libs)(exit)
This file uses the newlisp armory module, refer to my GitHub project: https://github.com/csfreebird/newlisp_armory
The tmpl. LSP file is used to process the cppcms tmpl file. The Code is as follows:
(define (get-extension name) (first (regex "[^.]*$" name)) );; @syntax (remove-extension name);; @return file name without extension;; @note remove extension name e.g a.b .b is extension, it will be removed(define (remove-extension name) ((regex "(.*)\\.(.*)$" name) 3) );; @syntax (tmpl-to-cc);; @note find all tmpl files in tmpl-folder, translate them into *.cc files(define (tmpl-to-cc tmpl-folder cc-folder) (set 'tmpl-files (directory tmpl-folder "\\.tmpl")) (set 'cmd-tmpl (append "cppcms_tmpl_cc " tmpl-folder "/%s -o " cc-folder "/%s.cc")) (dolist (tmpl-file tmpl-files) (set 'cmd (format cmd-tmpl tmpl-file (remove-extension tmpl-file))) (println cmd) (exec cmd) ))
G ++. LSP generates the G ++ command. The file content is as follows:
;; @syntax (compile include-dirs src-dirs o-dir);; @parameter include-dir a list contains one or more relative or absolute include directories;; @parameter src-dirs a list contains one or more relative or absolute src dirs(define (compile include-dirs src-dirs o-dir) (if (directory? o-dir) (file:clean-folder o-dir) (make-dir o-dir)) (set 'path1 "") (dolist (path include-dirs) (set 'path1 (append path1 "-I" path " "))) (set 'cmd-template (format "/usr/bin/c++ -g %s -Wall -o %s/" path1 o-dir)) (dolist (dir src-dirs) (compile-dir dir cmd-template) ) );; @syntax (compile-dir dir cmd-template);; @parameter dir one folder which contains many .cc or .cpp files;; @parameter cmd-template the command template that has -g, -Wall and -I args (define (compile-dir dir cmd-template) (set 'file-list (directory dir "\\.cc|\\.cpp")) (println "dir: " dir) (dolist (cc-path file-list) (set 'str (append cc-path ".o")) (set 'cmd (append cmd-template str " -c " dir "/" cc-path)) (println cmd) (exec cmd)) );; @syntax (dynamic-link o-dir bin-dir binary-name libs);; @parameter o-dir the direcotry includs all .o files;; @parameter bin-dir the location of linked binary file;; @libs the list of all dependencies(define (dynamic-link o-dir bin-dir binary-name libs) (if (directory? bin-dir) (file:clean-folder bin-dir) (make-dir bin-dir)) (set 'cmd "/usr/bin/c++ -g") (set 'o-files (directory o-dir "\\.o")) (dolist (o-file o-files) (set 'cmd (append cmd " " (real-path o-dir) "/" o-file))) (set 'cmd (append cmd " -o " bin-dir "/" binary-name " -rdynamic")) (dolist (lib libs) (set 'cmd (append cmd " -l" lib))) (println cmd) (exec cmd) );; @syntax (static-link o-dir bin-dir binary-name libs);; @parameter o-dir the direcotry includs all .o files;; @parameter bin-dir the location of linked binary file;; @libs the list of all dependencies(define (static-link o-dir bin-dir binary-name libs) (if (directory? bin-dir) (file:clean-folder bin-dir) (make-dir bin-dir)) (set 'cmd "/usr/bin/c++ -g ") (set 'o-files (directory o-dir "\\.o")) (dolist (o-file o-files) (set 'cmd (append cmd " " (real-path o-dir) "/" o-file))) (set 'cmd (append cmd " -o " bin-dir "/" binary-name " -static-libgcc -static-libstdc++ -static -L/usr/lib/x86_64-linux-gnu")) (dolist (lib libs) (set 'cmd (append cmd " -l" lib)) (println cmd)) (exec cmd) )
For ease of use, a compile. LSP file is provided for compilation and can be run directly.
;; compile all c++ files to .o file in ./o folder(load "g++.lsp")(set 'include-paths (list "../codes/main/include" "../codes/main/src/../../loki-0.1.7/include"))(set 'o-dir "./o")(set 'src-paths (list "../codes/main/src" "../codes/main/src/bean" "../codes/main/src/controller" "../codes/main/src/helper" "../codes/main/src/module" "../codes/main/src/service" "../codes/main/src/view" ))(compile include-paths src-paths o-dir)(exit)
Dlink. LSP
#!/usr/bin/newlisp ;; init(load "/opt/build_config.lsp")(set 'armory-folder (env "NEWLISP_ARMORY_HOME"))(println (append "newlisp armory home folder: " armory-folder))(load (append armory-folder "/codes/file/file.lsp"))(file:init);; compile all c++ files to .o file in ./o folder(load "g++.lsp")(set 'o-dir "./o");; link all .o files(set 'libs (list "pthread" "cppcms" "mongoclient" "booster" "loki" "cryptopp" "boost_system" "boost_thread" "boost_filesystem" ))(set 'binary-name "sports_lottery_d")(set 'bin-dir "bin")(dynamic-link o-dir bin-dir binary-name libs)(exit)
Dedicated static link file Slink. LSP
#!/usr/bin/newlisp ;; init(load "/opt/build_config.lsp")(set 'armory-folder (env "NEWLISP_ARMORY_HOME"))(println (append "newlisp armory home folder: " armory-folder))(load (append armory-folder "/codes/file/file.lsp"))(file:init);; compile all c++ files to .o file in ./o folder(load "g++.lsp")(set 'o-dir "./o");; link all .o files(set 'libs (list "mongoclient" "cppcms" "booster" "boost_system" "loki" "cryptopp" "boost_thread" "pthread" "boost_filesystem" "dl" "gcrypt" "z" "pcre" "icuuc" "icui18n" "gpg-error" "icuuc" "icudata" ))(set 'binary-name "sports_lottery_s")(set 'bin-dir "bin")(static-link o-dir bin-dir binary-name libs)(exit)
Note that the names and sequence of these static libraries in Slink. LSP are constantly tried. I have summarized a good method:
1. A depends on B, and a must appear before B
2. Add only one library named client at the beginning, check the connector for errors, and find the missing library. Then, use LDD to find the correct library name and add it to the end. In this way, you can find all the static databases.
Newlisp is a powerful script tool that constantly improves my life. It will be improved in the future and put into my own GitHub project.