ObjectiveC project organization - objective-c

I wonder what is the more appropriate structure for a Objective-C project (a project that have more than ten classes...).
Code source
I put each class declaration and implementation respectively in a .h and .m files. Moreover I organize these files within a tree of folders. I don't want to have all my source files in a single folder. Is it the best approach for such project?
Building
What is the best approach to build Objective-C applications? I see that using makefile is possible but it seems that you need to specify all involved source files... Is it possible to have something to simply configure all source files for the build?
Packaging
What is the way to package the application in order to provide it as a library?
Thanks very much for your help!
Thierry

Code source
Putting relevant .h and .m files together in a subdirectory is fine. If you want the traditional Unix source layout, then put these subfolders into a directory named src, let your makefile build the library and intermediate object fiels into a filder named bld and put your Makefile in the top level directory, along with a LICENSE, a README and a CHANGELOG file.
Building
Using Makefile syntax, you can let Make build all source files into one library. Google a Makefile tutorial, but I can tell you that you probably want is something like
OBJECTS = $(patsubst %.o, %.m, $(wildcard Helpers/*.m))
OBJECTS += $(patsubst %.o, %.m, $(wildcard Network/*.m))
OBJECTS += $(patsubst %.o, %.m, $(wildcard External/*.m))
etc.
Packaging
I don't really understand this part of your question. How do you want to release it? You can distribute the source, and put into a tar(.gz or .bz2)ball. Or upload it to GitHub. Or build the source for some platforms, and make a DEB or RPM package out of the builds. It's difficult to tell in general, as every platform has something else (and not very specific) as convention.

Related

How I can build the big library using cmake?

I have a lot folders from sources which contents .cpp and .h files. Each folder contains CMakeLists.txt file except folders which contents .h headers files. I see the several ways.
The first way is consist from take advantage of add_library(myLib1 STATIC /link/to/sources/somefile.cpp /link/to/sources/interfaces/somefile.h). But in this way I will have a lot strings when is't good way, I think. Because I have very more files, which are interconnected.
The same way, with that exception when use set(HEADERS /link1 /link2 ....) and set(SOURCES /link3 ...) and than add_library(myLib ${HEADERS} ${SOURCES}).
I think than both the ways is't do properly. I don't know how I can connect the folder with library into my project, because if include this using the above methods it's will take a long time and is't beautiful

Hierarchical CMake project that also works when building an "inner" (non-root) project

Suppose I have a hierarchical CMake project, composed of n different projects:
CMakeLists.txt
proj-1/CMakeLists.txt
proj-2/CMakeLists.txt
(...)
proj-n/CMakeLists.txt
Evidently there'll be the source files for each project as well.
I'd ensure all commands of interest are added to the root CMakeLists.txt file -- say, CMAKE_CXX_STANDARD, enable_testing(), add_compile_options(), etc. If I understand correctly, whichever options are included in the root CMakeLists.txt file are also applied to all children CMakeLists.txt file -- please correct me if I'm wrong, since I'm counting on this behavior. The root CMakeLists.txt also contains an add_subdirectory(proj-X) statement for each X = 1, ..., n.
Anyway. Suppose, for some reason, that I would like to build only one of the proj-X folders, say proj-1. Maybe the build is broken in one of the other projects, or maybe I need to fix a bug on proj-1, it doesn't depend on the other projects, and it would take forever to build all projects.
The point is: I would like to run cmake on proj-1/CMakeLists.txt rather than on the root CMakeLists.txt file, and yet I would like to ensure that proj-1 is built in exactly the same way it would be build, had I run cmake on the root CMakeLists.txt file. This is an issue since the root CMakeLists.txt contains statements that the children CMakeLists.txt should "inherit" from in the regular situation where it's built from the root, and yet in this scenario I'm building directly from proj-1/CMakeLists.txt (the root CMakeLists.txt file doesn't come into the picture in this scenario.)
One possibility, as I understand, would be to copy all options from the root CMakeLists.txt file to every other proj-X/CMakeLists.txt file. Of course, this is a hack and a maintenance nightmare, but I suppose it would work.
Are there other possible solutions? Can I, say, create a file containing all the common options and save it to the root, and then do the CMake equivalent of #include within each of the proj-X/CMakeLists.txt files? Would there be an issue due to running the same commands twice (once on the root CMakeLists.txt and another on the proj-X/CMakeLists.txt file, when starting the build from the root)?
You may need to rework some of your CMakeLists.txt files.
I would recommend watching Daniel Pfeifer's Effective CMake talk at CPPcon (slides available here).
The gist of it is that all of your projects should provide everything they need in order to be build or compiled, in essence build requirements and usage requirements. To achieve this in a maintainable and scalable way you have to move away from variables and setting global options (add_compile_options, include_directories, etc) and instead focus on targets (target_compile_options, target_include_directories, etc).
So, in your case proj-1/CMakeLists.txt will provide one target (let's call it proj::proj1) that sets the proper PUBLIC and INTERFACE options (by options I mean needed compiler features, dependencies, include directories, etc).
An abstract example:
project(proj1)
add_library(proj1 src.cpp)
# This are private include files, whoever uses this library does not need them
target_include_directories(proj1 PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include)
# These are public, needed both by this target and by whoever uses it.
target_include_directories(proj1 PUBLIC
# This is used when building the target
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/public/include>
# This is used when the target is installed
$<INSTALL_INTERFACE:include>)
# Instead of asking directly for a language standard we ask for a compiler feature. We make this public so whoever depends on this target knows they also need this feature.
target_compile_features(proj1 PUBLIC cxx_strong_enums)
# As above, but this is needed only by this target during the build.
target_compile_features(proe1 PRIVATE cxx_lambdas)
# Add an alias, users can use target_link_libraries(target PRIVATE|PUBLIC proj::proj1) to add this target as a dependency (this will propagate all the PUBLIC include paths, compile options, compile features, dependencies, etc.
add_library(proj::proj1 ALIAS proj1)
This is highly abstract, it depends on what you're actually doing in your build scripts, it's hard to give a better explanation than Daniel Pfeifer, so I recommend watching his talk or at least reading the slides. It will make your build scripts a lot easier to write, read, and use.
Another great resource is this site.

Can CMakeLists.txt depend on a file parsed by a function?

I am rather new to CMake, starting off for the first time with a larger project consisting of many subprojects.
For particular reasons (described below for the curious) I already have a set of include files that contain info about the source files needed for each CMake target (lib or exe) – and, for now, I prefer to (re)use these files (reason also described below)
Writing a function to parse these files and add their content as source files to the targets was a surprisingly easy task.
But – now the Problem:
Obviously I want to have each targets CMakeLists.txt depend on the particular include file, that generates the list of source files, so that changes on the include file will be detected as if it were changes to CMakeLists.txt itself, but I simply can’t find any references on how to accomplish that.
N.B.: I found AddFileDependencies but that is for adding dependencies on source files, not the CMakeLists.txt. However, CMake itself can figure out dependencies to included .cmake file somehow, so I figured, it should be possible to do somehow.
Background for the curious:
For this project (quite a number of libraries used by quite a number of executable targets, all organized as subprojects) I was using QMake (without actually using Qt itself) for setting up makefiles. Doing so I was able to use Qt Creator while still being able to generate Visual Studio Solution/Project files automagically. We’re also still in progress of evaluating different IDEs and the choice has not been made yet. But the most important reason to use a generator like QMake / CMake was not being forced to set up the VS files for all these subprojects manually.
Although I needed to trick QMake sometimes to do what I wanted to, things went quite well - even for the VS solution - except for one thing: Visual Studio messes up dependencies on Flex/Bison and other files using custom build rules. It keeps recompiling the Flex/Bison/other files saying „command line changed“ – which I gave up trying to fix.
For this reason I thougt, I’d try CMake as a generator instead, which looks very promising so far – although not having builtin precompiled header support in CMake is somewhat ridiculous these days (off topic, I know).
Since Qt Creators CMake support is by far not as good as the support for QMake projects, I firgured, using the approach of parsing the .pri files containing the source file list would enable me using QMake and CMake side by side – especially since the remaining project settings are rather less complicated than on most open source projects.
There's a nice trick which does exactly what you need. It's based on the idea I found in the git-revision module of #rpavlik see this so question
This is the overall idea:
Create a dummy timestamp file
Add a custom command which touches the timestamp whenever the input .pri file changes
include the timestamp file in your CMakeLists.txt
A possible implementation:
set(input_pri_file <path-to-the-input-pri-file>)
set(timestamp_file ${CMAKE_CURRENT_BINARY_DIR}/timestamp.cmake)
add_custom_command(
OUTPUT ${timestamp_file}
COMMAND ${CMAKE_COMMAND} -E touch ${timestamp_file}
MAIN_DEPENDENCY ${input_pri_file}
VERBATIM
COMMENT "Updating timestamp.cmake"
)
if(NOT EXISTS "${timestamp_file}")
file(WRITE ${timestamp_file} "") # create initial empty file
endif()
include(${timestamp_file})
# create the file list from input_pri_file
....
# use the file list
add_executable(main ${filelist})
Here's what happens when the .pri file changes:
the change triggers the execution of the custom command
which updates the timestamp
because the CMakeLists includes the timestamp it is dependent on it
so updating the timestamp triggers a re-configuration of the CMakeLists.txt
I use the configure_file() if I have some input that should retrigger CMake's configuration process. See e.g. How to make CMake reconfiguration depend on custom file? and configure_file()'s unit test
So in your case it would look something like:
configure_file(SomeInput.pri ${CMAKE_CURRENT_BINARY_DIR}/SomeInput.pri)
Then you use ${CMAKE_CURRENT_BINARY_DIR}/SomeInput.pri to generate the sources. Just make sure you do not add COPYONLY, because then configuration won't retrigger on changes of SomeInput.pri.
EDIT: Alternatively use - a relative new addition - the CMAKE_CONFIGURE_DEPENDS directory property.

How to reuse Fortran modules without copying source or creating libraries

I'm having trouble understanding if/how to share code among several Fortran projects without building libraries or duplicating source code.
I am using Eclipse/Photran with the Intel compiler (ifort) on a linux system, but I believe I'm having a bigger conceptual problem with modules than with the specific tools.
Here's a simple example: In ~/workspace/cow I have a source directory (src) containing cow.f90 (the PROGRAM) and two modules m_graze and m_moo in m_graze.f90 and m_moo.f90, respectively. This project builds and links properly to create the executable 'cow'. The executable and modules (m_graze.mod and m_moo.mod) are stored in ~/workspace/cow/Debug and object files are stored under ~/workspace/cow/Debug/src
Later, I create ~/workplace/sheep and have src/sheep.f90 as the program and src/m_baa.f90 as the module m_baa. I want to 'use m_graze, only: ruminate' in sheep.f90 to get access to the ruminate() subroutine. I could just copy m_graze.f90 but that could lead to code getting out of sync and doesn't take into account any dependencies m_graze might have. For these reasons, I'd rather leave m_graze in the cow project and compile and link sheep.f90 against it.
If I try to compile the sheep project, I'll get an error like:
error #7002: Error in opening the compiled module file. Check INCLUDE paths. [M_GRAZE]
Under Properties:Project References for sheep, I can select the cow project. Under Properties:Fortran Build:Settings:Intel Compiler:Preprocessor I can add ~/workspace/cow/Debug (location of the module files) to the list of include directories so the compiler now finds the cow modules and compiles sheep.f90. However the linker dies with something like:
Building target: sheep
Invoking: Intel(R) Fortran Linker
ifort -L/home/me/workspace/cow/Debug -o "sheep" ./src/sheep.o
./src/sheep.o: In function `sheep':
/home/me/workspace/sheep/src/sheep.f90:11: undefined reference to `m_graze_mp_ruminate_'
This would normally be solved by adding libraries and library paths to the linker settings except there are no appropriate libraries to link to (this is Fortran, not C.)
The cow project was perfectly capable of compiling and linking together cow.f90, m_graze.f90 and m_moo.f90 into an executable. Yet while the sheep project can compile sheep.f90 and m_baa.f90 and can find the module m_graze.mod, it can't seem to find the symbols for m_graze even though all the requisite information is present on the system for it to do so.
It would seem to be an easy matter of configuration to get the linker portion of ifort to find the missing pieces and put them together but I have no idea what magic words need to be entered where in the Photran UI to make this happen.
I confess an utter lack of interest and competence in C and the C build process and I'd rather avoid the diversion of creating libraries (.a or .so) unless that's the only way to make this work.
Ultimately, I'm looking for a pure Fortran solution to this problem so I can keep a single copy of the source code and don't have to manually maintain a pile of custom Makefiles.
So can this be done?
Apologies if this has already been documented somewhere; Google is only showing me simple build examples, how to create modules, and how to link with existing libraries. There don't seem to be (m)any examples of code reuse with modules that don't involve duplicating source code.
Edit
As respondents have pointed out, the .mod files are necessary but not sufficient; either object code (in the form of m_graze.o) or static or shared libraries must be specified during the linking phase. The .mod files describe the interface to the object code/library but both are necessary to build the final executable.
For an oversimplified toy problem such as this, that's sufficient to answer the question as posed.
In a larger project with more complex dependencies (in my case, 80+KLOC of F90 linking to the MKL version of LAPACK95), the IDE or toolchain may lack sufficient automatic or user-interface facilities to make sharing a single canonical set of source files a viable strategy. The choice seems to be between risking duplicate source files getting out of sync, giving up many of the benefits of an IDE (i.e. avoiding manual creation of make/CMake/SCons files), or, in all likelihood, both. While a revision control system and good code organization can help, it's clear that sharing a single canonical set of source files among projects is far from easy given the current state of Eclipse.
Some background which I suspect you already know: Typically (including ifort) compiling the source code for a Fortran module results in two outputs - a "mod" file that contains a description of the Fortran entities that the module defines that the compiler needs to find whenever it sees a USE statement for the module, and object code for the linker that implements the procedures and variable storage, etc., that the module defines.
Your first error (the one you solved) is because the compiler couldn't find the mod file.
The second error is because the linker hasn't been told about the object code that implements the stuff that was in the source file with the module. I'm not an Eclipse user by any means, but a brute force way of specifying that is just to add the object file (xxxxx/Debug/m_graze.o) as an additional linker option (Fortran Build > Settings, under Intel Fortran Linker > Command Line). (Other tool chains have explicit "additional object file" properties for their link stage - there may well be a better way of doing this for the Intel chain.)
For more involved examples you would typically create a library out of the shared code. That's not really C specific, the only Fortran aspect is that the libraries archive of object code needs to be provided alongside the mod files that the Fortran compiler generates.
Yes the object code must be provided. E.g., when you install libnetcdf-dev in Debian (apt-get install libnetcdf-dev), there is a /usr/include/netcdf.mod file that is included.
You can now use all netcdf routines in your Fortran code. E.g.,
program main
use netcdf
...
end
but you'll have link to the netcdf shared (or static) library, i.e.,
gfortran -I/usr/include/ main.f90 -lnetcdff
However, as user MSB mentioned the mod file can only be used by gfortran that comes with the distribution (apt-get install gfortran). If you want to use any other compiler (even a different version that you may have installed yourself) then you'll have to build netcdf yourself using that particular compiler.
So creating a library is not a bad solution.

How to add to project additional files not intended to be compiled?

I would like to add into project some files that shouldn't be compiled. I mean mainly text files with for example notes, concepts, comments etc.
I realized that it is possible only at module level. But it is not very convenient. I'd rather prefer to keep them on project level. Is it possible in any way?
And if not:
I have another idea: to create special module, name it for example "other_stuff", do not create src directory and put files there. Is it ok? I'm afraid of potential compilation problems when one of modules is artificial, with no sources but still has sdk assigned (it is probably impossible to leave module without sdk assigned).
While generating artifacts you can add any file into your artifact. Also, in modules you can have folders not declared as source, and they will not be compiled.