Back Midas Rome Roody Rootana
  Midas DAQ System, Page 92 of 146  Not logged in ELOG logo
ID Date Author Topic Subjectdown
  644   21 Sep 2009 Stefan RittInfoNew feature: Stop run after a certain time
A new feature has been implemented in revision 4561 which allows runs with a 
certain duration. To use this, one has to set the variaable

/Logger/Run Duration

to a non-zero value in seconds. After a run lasted for this duration, it gets 
stopped automatically by the logger. If the auto-restart flag is on, this allows 
sequences of automatically started and stopped runs with all then have the same 
duration.
  645   22 Sep 2009 Stefan RittInfoNew feature: Stop run after a certain time
> A new feature has been implemented in revision 4561 which allows runs with a 
> certain duration. To use this, one has to set the variaable
> 
> /Logger/Run Duration
> 
> to a non-zero value in seconds. After a run lasted for this duration, it gets 
> stopped automatically by the logger. If the auto-restart flag is on, this allows 
> sequences of automatically started and stopped runs with all then have the same 
> duration.

A similar scheme has been implemented to pose a certain duration on subruns. This can 
be controlled by the variable

/Logger/Subrun duration

when set to a non-zero value in seconds.
  2160   06 May 2021 Ben SmithInfoNew feature in odbxx that works like db_check_record()
For those unfamiliar, odbxx is the interface that looks like a C++ map, but automatically syncs with the ODB - https://midas.triumf.ca/MidasWiki/index.php/Odbxx.

I've added a new feature that is similar to the existing odb::connect() function, but works like the old db_check_record(). The new odb::connect_and_fix_structure() function:
- keeps the existing value of any keys that are in both the ODB and your code
- creates any keys that are in your code but not yet in the ODB
- deletes any keys that are in the ODB but not your code
- updates the order of keys in the ODB to match your code

This will hopefully make it easier to automate ODB structure changes when you add/remove keys from a frontend.

The new feature is currently in the develop branch, and should be included in the next release.
  2619   06 Oct 2023 Stefan RittInfoNew equipment display
Since a long time we tried to convert all "static" mhttpd-generated pages to 
dynamic JavaScript. With the new history panel editor we were almost there. Now I 
committed the last missing piece - the equipment display. This is shown when you 
click on some equipment on the main status page, or if you define some Alias with 

?cmd=eqtable&eq=Trigger

This is now a dynamic display, so the values change if they change in the ODB. The 
also flash briefly in yellow to visually highlight any change. In addition, these 
pages have a unit display, and some values can be edited. This is controlled by 
following settings:

/Equipment/<name>/settings/Unit <variable>

where <name> is the name of the equipment and <variable> the variable array name 
under /Equipment/<name>/Variables/<variable>

If the unit setting is not present, just a blank column is shown.

The other setting is

/Equipment/<name>/settings/Editable 

which may contain a comma-separated string of variables which can be editied on 
the equipment page.

In addition, one can save/export the equipment in a json file, which is the same 
as a ODB save of that branch. A load or import however only loads values into the 
ODB which are under the "Editable" setting above. This allows a simple editor for 
HV values etc.

Stefan
  2620   09 Oct 2023 Stefan RittInfoNew equipment display
An additional functionality has been implemented on the equipment table:

You can now select several elements by Ctrl/Shift-Click on their names, then change the 
first one. After a confirmation dialog, all selected variables are then set to the new 
value. This way one can very easily change all values to zero etc.

Stefan
Attachment 1: Screenshot_2023-10-09_at_21.56.25.png
Screenshot_2023-10-09_at_21.56.25.png
  2514   12 May 2023 Stefan RittInfoNew environment variable MIDAS_EXPNAME
A new environment variable MIDAS_EXPNAME has been introduced. This must be
used for cases where people use MIDAS_DIR, and is then equivalent for the
experiment name and directory usually used in the exptab file. This fixes
and issue with creating and deleting shared memory in midas as described in

https://bitbucket.org/tmidas/midas/issues/363/deletion-of-shared-memory-fails

The documentation has been updated at

https://daq00.triumf.ca/MidasWiki/index.php/MIDAS_environment_variables#MIDAS_EXPN
AME

/Stefan
  2515   12 May 2023 Konstantin OlchanskiInfoNew environment variable MIDAS_EXPNAME
> A new environment variable MIDAS_EXPNAME has been introduced [to be used together with 
MIDAS_DIR]

This is fixes an important buglet. If experiment uses MIDAS_DIR instead of exptab, at the time 
of connecting to ODB, we do not know the experiment name and use name "Default" to create ODB 
shared memory, instead of actual experiment name.

This creates an inconsistency, if some MIDAS programs in the same experiment use MIDAS_DIR while 
others use exptab (this would be unusual, but not impossible) they would connect to two 
different ODB shared memories, former using name "Default", latter using actual experiment name.

As an indication that something is not right, when stopping MIDAS programs, there is an error 
message about failure to delete shared ODB shared memory (because it was created using name 
"Default" and delete using the correct experiment name fails).

Also it can cause co-mingling between two different experiments, depending on the type of shared 
memory used by MIDAS (see $MIDAS_DIR/.SHM_TYPE.TXT):
POSIX - (usually not used) not affected (experiment name is not used)
POSIXv2 - (usually not used) affected (shm name is "$EXP_NAME_ODB")
POSIXv3 - used on MacOS - affected (shm name is "$UID_$EXP_NAME_ODB" so "$UID_Default_ODB" will 
collide)
POSIXv4 - used on Linux - not affected (shm name includes $MIDAS_DIR which is different for 
different experiments)

K.O.
  2542   20 Jun 2023 Stefan RittInfoNew environment variable MIDAS_EXPNAME
I just realized that we had already MIDAS_EXPT_NAME, and now people get confused with

MIDAS_EXPT_NAME
and
MIDAS_EXPNAME

In trying to fix this confusion, I changed the name of the second variable to MIDAS_EXPT_NAME as well, 
so we only have one variable now. If this causes any problems please report here.

Stefan
  2564   28 Jul 2023 Stefan RittInfoNew environment variable MIDAS_EXPNAME
Concerning naming of shared memories I went one step further due to some requirement of a local experiment. 
The experiment needs to change the experiment name shown on the web status page depending on the exact 
configuration, but we do not want to change the whole midas experiment each time.

So I simple removed the check that the experiment name coming from the environment and used for the shared 
memory gets checked against the experiment name in the ODB. The only connection there is that the ODB name 
gets set to the environment name is it does not exist or is empty, just to have some default value. So for 
most people nothing should change. If one changes however the name in the ODB (under /Experiment/Name), 
nothing will change internally, just the web display via mhttpd changes its title.

I hope this has no bad side-effects, so please have a look if you see any issue in your experiment.

Stefan
  668   02 Nov 2009 Exaos LeeSuggestionNew cmake files
Though ended with ".c", "lazylogger.c" has to be build with C++ compiler. I have 
to modify my CMakeLists.txt. 
Please see the attachment if you need it. It works with svn-r4616.
Attachment 1: cmake4midas.zip
  2921   12 Dec 2024 Stefan RittSuggestionNew alarm sound flag to be tested
We had the case in MEG that some alarms were actually just warnings, not very severe. This happens for example if we calibrate our detector 
once every other day and modify the hardware which actually triggers the alarm for about an hour or so.

The problem with this is now that the alarm sounds every few minutes, and people get annoyed during that hour. They turn down the volume 
of their speakers, or even disable the alarm sound. If the detector gets back into the default mode again, they might forget to re-enable the 
alarm, which causes some risk. 

Turning down the volume is also not good, since during that hour we could have a "real" alarm on which people have to react quickly in order 
not destroy the detector.

The art is now to configure the alarm system in a way that "normal" changes do not annoy people or cover up really severe alarms. After long 
discussions we came to following conclusion: We need a special class of alarm (let's call it 'warning') which does not annoy people. The 
warning should be visible on the screen, but not ring the alarm bell. 

While we have different alarm classes in midas, which let us customize the frequency of alarms and the screen colors, all alarms or warnings 
ring the alarm sound right now. This can be changed in the browser under "Config/Alarm sound" but that switch affects ALL alarms, which is 
not what we want.

The idea we came up with was to add a flag "Alarm sound" to the alarm classes. For the 'warning' we can then turn off the alarm sound, so 
only the banner is shown on top of the screen, and the spoken message is generated every 15 mins to remind people, but not to annoy them.

I added this "Alarm sound" flag in the branch feature/alarm_sound so everybody can test it. The downside is that all "Alarm/Classs/xxx" need 
to be modified to add this flag. While the new code will add this flag automatically (with a default value of 'true'), the size of the alarm class 
record changes by four bytes (one bool). Therefore, all running midas programs will complain about the changed size, until they get 
recompiled. 

Therefore, to test the new feature, you have to checkout the branch and  re-compile all midas programs you use, otherwise you will get errors 
like 

  Fixing ODB "/Alarms/Classes/Alarm" struct size mismatch (expected 352, odb size 348)

I will keep the branch for a few days for people to try it out and report any issue, and later merge it to develop.

Stefan
  2925   19 Dec 2024 Stefan RittSuggestionNew alarm count added
Another modification has been done to the alarm system. 

We have often cases where an alarm is triggered on some readout noise. Like an analog voltage just over the alarm threshold for a very short period of time, triggered sometimes from environmental 
electromagnetic effects like turning on the light. 

To mitigate this problem, an "alarm trigger count" has been implemented. Every alarm has now a variable "Trigger count required". If this value is zero (the default), the alarm system works as before. If this 
value is nowever set to a non-zero value N, the alarm limit has to be met on N consecutive periods in order to trigger the alarm. Each alarm has a "Check interval" which determines the period of the alarm 
checking. If one has for example:

Check interval = 10
Trigger count required = 3

then the alarm condition has to be met for 3 consecutive periods of 10 seconds each, or for 30 seconds in total. 

The modification has been merged into the develop branch, and people have to be aware that the alarm structures in the ODB changed. The current code tries to fix this automatically, but it is important 
that ALL MIDAS CLIENTS GET RE-COMPILED after the new code is applied. Otherwise we could have "new" clients expecting the new ODB structure, and some "old" clients expecting the old structure, 
then both types of clients would fight against each other and change the ODB structure every few seconds, leading to tons of error messages. So if you pull the current develop branch, make sure to re-
compile ALL midas clients.

/Stefan
  1906   12 May 2020 Stefan RittInfoNew ODB++ API
Since the beginning of the lockdown I have been working hard on a new object-oriented interface to the online database ODB. I have the code now in an initial state where it is ready for 
testing and commenting. The basic idea is that there is an object midas::odb, which represents a value or a sub-tree in the ODB. Reading, writing and watching is done through this 
object. To get started, the new API has to be included with

   #include <odbxx.hxx>

To create ODB values under a certain sub-directory, you can either create one key at a time like:

   midas::odb o;
   o.connect("/Test/Settings", true);   // this creates /Test/Settings
   o.set_auto_create(true);            // this turns on auto-creation
   o["Int32 Key"] = 1;                 // create all these keys with different types
   o["Double Key"] = 1.23;
   o["String Key"] = "Hello";

or you can create a whole sub-tree at once like:

  midas::odb o = {
    {"Int32 Key", 1},
    {"Double Key", 1.23},
    {"String Key", "Hello"},
    {"Subdir", {
      {"Another value", 1.2f}
    }
  };
  o.connect("/Test/Settings");

To read and write to the ODB, just read and write to the odb object

   int i = o["Int32 Key];
   o["Int32 Key"] = 42;
   std::cout << o << std::endl;

This works with basic types, strings, std::array and std::vector. Each read access to this object triggers an underlying read from the ODB, and each write access triggers a write to the 
ODB. To watch a value for change in the odb (the old db_watch() function), you can use now c++ lambdas like:

   o.watch([](midas::odb &o) {
      std::cout << "Value of key \"" + o.get_full_path() + "\" changed to " << o << std::endl;
   });

Attached is a full running example, which is now also part of the midas repository. I have tested most things, but would not yet use it in a production environment. Not 100% sure if there 
are any memory leaks. If someone could valgrind the test program, I would appreciate (currently does not work on my Mac).

Have fun!

Stefan

  
Attachment 1: odbxx_test.cxx
/********************************************************************\

  Name:         odbxx_test.cxx
  Created by:   Stefan Ritt

  Contents:     Test and Demo of Object oriented interface to ODB

\********************************************************************/

#include <string>
#include <iostream>
#include <array>
#include <functional>

#include "odbxx.hxx"
#include "midas.h"

/*------------------------------------------------------------------*/

int main() {

   cm_connect_experiment(NULL, NULL, "test", NULL);
   midas::odb::set_debug(true);

   // create ODB structure...
   midas::odb o = {
           {"Int32 Key", 42},
           {"Bool Key", true},
           {"Subdir", {
              {"Int32 key", 123 },
              {"Double Key", 1.2},
              {"Subsub", {
                 {"Float key", 1.2f},     // floats must be explicitly specified
                 {"String Key", "Hello"},
              }}
           }},
           {"Int Array", {1, 2, 3}},
           {"Double Array", {1.2, 2.3, 3.4}},
           {"String Array", {"Hello1", "Hello2", "Hello3"}},
           {"Large Array", std::array<int, 10>{} },   // array with explicit size
           {"Large String", std::string(63, '\0') },  // string with explicit size
   };

   // ...and push it to ODB. If keys are present in the
   // ODB, their value is kept. If not, the default values
   // from above are copied to the ODB
   o.connect("/Test/Settings", true);

   // alternatively, a structure can be created from an existing ODB subtree
   midas::odb o2("/Test/Settings/Subdir");
   std::cout << o2 << std::endl;

   // retrieve, set, and change ODB value
   int i = o["Int32 Key"];
   o["Int32 Key"] = i+1;
   o["Int32 Key"]++;
   o["Int32 Key"] *= 1.3;
   std::cout << "Should be 57: " << o["Int32 Key"] << std::endl;

   // test with bool
   o["Bool Key"] = !o["Bool Key"];

   // test with std::string
   std::string s = o["Subdir"]["Subsub"]["String Key"];
   s += " world!";
   o["Subdir"]["Subsub"]["String Key"] = s;

   // test with a vector
   std::vector<int> v = o["Int Array"];
   v[1] = 10;
   o["Int Array"] = v;        // assign vector to ODB object
   o["Int Array"][1] = 2;     // modify ODB object directly
   i = o["Int Array"][1];     // read from ODB object
   o["Int Array"].resize(5);  // resize array
   o["Int Array"]++;          // increment all values of array

   // test with a string vector
   std::vector<std::string> sv;
   sv = o["String Array"];
   sv[1] = "New String";
   o["String Array"] = sv;
   o["String Array"][2] = "Another String";

   // iterate over array
   int sum = 0;
   for (int e : o["Int Array"])
      sum += e;
   std::cout << "Sum should be 11: " << sum << std::endl;

   // creat key from other key
   midas::odb oi(o["Int32 Key"]);
   oi = 123;

   // test auto refresh
   std::cout << oi << std::endl;    // each read access reads value from ODB
   oi.set_auto_refresh_read(false); // turn off auto refresh
   std::cout << oi << std::endl;    // this does not read value from ODB
   oi.read();                       // this does manual read
   std::cout << oi << std::endl;

   midas::odb ox("/Test/Settings/OTF");
   ox.delete_key();

   // create ODB entries on-the-fly
   midas::odb ot;
   ot.connect("/Test/Settings/OTF", true);   // this forces /Test/OTF to be created if not already there
   ot.set_auto_create(true);        // this turns on auto-creation
   ot["Int32 Key"] = 1;             // create all these keys with different types
   ot["Double Key"] = 1.23;
   ot["String Key"] = "Hello";
   ot["Int Array"] = std::array<int, 10>{};
   ot["Subdir"]["Int32 Key"] = 42;
   ot["String Array"] = std::vector<std::string>{"S1", "S2", "S3"};
   std::cout << ot << std::endl;

   o.read();                        // re-read the underlying ODB tree which got changed by above OTF code
   std::cout << o.print() << std::endl;

   // iterate over sub-keys
   for (auto& oit : o)
      std::cout << oit.get_odb()->get_name() << std::endl;

   // print whole sub-tree
   std::cout << o.print() << std::endl;

   // dump whole subtree
   std::cout << o.dump() << std::endl;

   // delete test key from ODB
   o.delete_key();

   // watch ODB key for any change with lambda function
   midas::odb ow("/Experiment");
   ow.watch([](midas::odb &o) {
      std::cout << "Value of key \"" + o.get_full_path() + "\" changed to " << o << std::endl;
   });

   do {
      int status = cm_yield(100);
      if (status == SS_ABORT || status == RPC_SHUTDOWN)
         break;
   } while (!ss_kbhit());

   cm_disconnect_experiment();
   return 1;
}
  1913   20 May 2020 Konstantin OlchanskiInfoNew ODB++ API
>    midas::odb o;
>    o["foo"] = 1;

This is an excellent development.

ODB is a tree-structured database, JSON is a tree-structured data format,
and they seem to fit together like hand and glove. For programming
web pages, Javascript and JSON-style access to ODB seems to work really well.

And now with modern C++ we can have a similar API for working with ODB tree data,
as if it were Javascript JSON tree data.

Let's see how well it works in practice!

K.O.
  1914   20 May 2020 Stefan RittInfoNew ODB++ API
In meanwhile, there have been minor changes and improvements to the API:

Previously, we had:

>    midas::odb o;
>    o.connect("/Test/Settings", true);   // this creates /Test/Settings
>    o.set_auto_create(true);            // this turns on auto-creation
>    o["Int32 Key"] = 1;                 // create all these keys with different types
>    o["Double Key"] = 1.23;
>    o["String Key"] = "Hello";

Now, we only need:

      o.connect("/Test/Settings");
      o["Int32 Key"] = 1;                 // create all these keys with different types
      ...

no "true" needed any more. If the ODB tree does not exist, it gets created. Similarly, set_auto_create() can be dropped, it's on by default (thought this makes more sense). Also the iteration over subkeys has 
been changed slightly.

The full example attached has been updated accordingly. 

Best,
Stefan
Attachment 1: odbxx_test.cxx
/********************************************************************\

  Name:         odbxx_test.cxx
  Created by:   Stefan Ritt

  Contents:     Test and Demo of Object oriented interface to ODB

\********************************************************************/

#include <string>
#include <iostream>
#include <array>
#include <functional>

#include "midas.h"
#include "odbxx.hxx"

/*------------------------------------------------------------------*/

int main() {

   cm_connect_experiment(NULL, NULL, "test", NULL);
   midas::odb::set_debug(true);

   // create ODB structure...
   midas::odb o = {
      {"Int32 Key", 42},
      {"Bool Key", true},
      {"Subdir", {
         {"Int32 key", 123 },
         {"Double Key", 1.2},
         {"Subsub", {
            {"Float key", 1.2f},     // floats must be explicitly specified
            {"String Key", "Hello"},
         }}
      }},
      {"Int Array", {1, 2, 3}},
      {"Double Array", {1.2, 2.3, 3.4}},
      {"String Array", {"Hello1", "Hello2", "Hello3"}},
      {"Large Array", std::array<int, 10>{} },   // array with explicit size
      {"Large String", std::string(63, '\0') },  // string with explicit size
   };

   // ...and push it to ODB. If keys are present in the
   // ODB, their value is kept. If not, the default values
   // from above are copied to the ODB
   o.connect("/Test/Settings");

   // alternatively, a structure can be created from an existing ODB subtree
   midas::odb o2("/Test/Settings/Subdir");
   std::cout << o2 << std::endl;

   // set, retrieve, and change ODB value
   o["Int32 Key"] = 42;
   int i = o["Int32 Key"];
   o["Int32 Key"] = i+1;
   o["Int32 Key"]++;
   o["Int32 Key"] *= 1.3;
   std::cout << "Should be 57: " << o["Int32 Key"] << std::endl;

   // test with bool
   o["Bool Key"] = false;
   o["Bool Key"] = !o["Bool Key"];

   // test with std::string
   o["Subdir"]["Subsub"]["String Key"] = "Hello";
   std::string s = o["Subdir"]["Subsub"]["String Key"];
   s += " world!";
   o["Subdir"]["Subsub"]["String Key"] = s;

   // test with a vector
   std::vector<int> v = o["Int Array"]; // read vector
   std::fill(v.begin(), v.end(), 10);
   o["Int Array"] = v;        // assign vector to ODB array
   o["Int Array"][1] = 2;     // modify array element
   i = o["Int Array"][1];     // read from array element
   o["Int Array"].resize(5);  // resize array
   o["Int Array"]++;          // increment all values of array

   // test with a string vector
   std::vector<std::string> sv;
   sv = o["String Array"];
   sv[1] = "New String";
   o["String Array"] = sv;
   o["String Array"][2] = "Another String";

   // iterate over array
   int sum = 0;
   for (int e : o["Int Array"])
      sum += e;
   std::cout << "Sum should be 47: " << sum << std::endl;

   // creat key from other key
   midas::odb oi(o["Int32 Key"]);
   oi = 123;

   // test auto refresh
   std::cout << oi << std::endl;    // each read access reads value from ODB
   oi.set_auto_refresh_read(false); // turn off auto refresh
   std::cout << oi << std::endl;    // this does not read value from ODB
   oi.read();                       // this forces a manual read
   std::cout << oi << std::endl;

   // create ODB entries on-the-fly
   midas::odb ot;
   ot.connect("/Test/Settings/OTF");// this forces /Test/OTF to be created if not already there
   ot["Int32 Key"] = 1;             // create all these keys with different types
   ot["Double Key"] = 1.23;
   ot["String Key"] = "Hello";
   ot["Int Array"] = std::array<int, 10>{};
   ot["Subdir"]["Int32 Key"] = 42;
   ot["String Array"] = std::vector<std::string>{"S1", "S2", "S3"};
   std::cout << ot << std::endl;

   o.read();                        // re-read the underlying ODB tree which got changed by above OTF code
   std::cout << o.print() << std::endl;

   // iterate over sub-keys
   for (midas::odb& oit : o)
      std::cout << oit.get_name() << std::endl;

   // print whole sub-tree
   std::cout << o.print() << std::endl;

   // dump whole subtree
   std::cout << o.dump() << std::endl;

   // delete test key from ODB
   o.delete_key();

   // watch ODB key for any change with lambda function
   midas::odb ow("/Experiment");
   ow.watch([](midas::odb &o) {
      std::cout << "Value of key \"" + o.get_full_path() + "\" changed to " << o << std::endl;
   });

   do {
      int status = cm_yield(100);
      if (status == SS_ABORT || status == RPC_SHUTDOWN)
         break;
   } while (!ss_kbhit());

   cm_disconnect_experiment();
   return 1;
}
  1915   20 May 2020 Pintaudi GiorgioInfoNew ODB++ API
All this is very good news. I really wish this were available some months ago: it would have helped me immensely. The old C API was clunky at best.
I really like the idea and looking forward to using it (even if at the moment I do not have the need to) ...
  1916   20 May 2020 Konstantin OlchanskiInfoNew ODB++ API
> All this is very good news. I really wish this were available some months ago: it would have helped me immensely. The old C API was clunky at best.
> I really like the idea and looking forward to using it (even if at the moment I do not have the need to) ...

Yes, I have designed new C-style MIDAS ODB APIs twice now (VirtualOdb in ROOTANA and MVOdb in ROOTANA and MIDAS),
and I was never happy with the results. There is too many corner cases and odd behaviour. Let's see how
this C++ interface shakes out.

For use in analyzers, Stefan's C++ interface still need to be virtualized - right now it has only one implementation
with the MIDAS ODB backend. In analyzers, we need XML, JSON (and a NULL ODB) backends. The API looks
to be clean enough to add this, but I have not looked at the implementation yet. So "watch this space" as they say.

K.O.
  455   09 Mar 2008 Exaos LeeSuggestionNew Makefile for building MIDAS
I rewrote the Makefile for MIDAS in order to make it tidy. I tested it on my box
and it works here.
1. The full file is seperated to several parts
  a. initialized setup
  b. environment setup
  c. specify OS-specific flags
  d. processing environment for building flags
  e. targets
2. The file is less than 400 lines now. The original one is more than 500 lines.
3. The modified one is easy for debuging.

I tried to learn "autoconf" and "automake" in order to make building MIDAS more
compatible for various platforms. But I havn't enough time now. Hope somebody
can help it. The attached file is original named "Makefile.in" for using "autoconf".

:-)
Attachment 1: Makefile-by-EL
# initialized flags

#CC =
#FC = 
#LD =
CFLAGS   = -g -O3 -Wall -Wuninitialized -DINCLUDE_FTPLIB

###########################################################################
## Environments setup

## Prefix
ifndef PREFIX
PREFIX = /usr/local
endif

# User defined flags for compiler
USERFLAGS     =

# Do you need to compile the shared library? If so, set "1" here.
NEED_SHLIB    =

# If RPATH needed ...
NEED_RPATH    =

# If static ROOT libaries needed ...
NEED_LIBROOTA =

# If strlcpy.o needed ...
NEED_STRLCPY  = 1

# If zlib needed ...
NEED_ZLIB     =

# MIDAS max event size
MIDAS_MAX_EVENT_SIZE =

# OS specific programs included
SPECIFIC_OS_PRG      =

# ..? Why it is needed?
MIDAS_PREF_FLAGS     =

## installer

INSTALL  = $(shell which install)
ifndef INSTALL
INSTALL  = ./install.sh
else
INS_OPTS = -v -D
endif

# MXML dir
ifndef MXML_DIR
MXML_DIR = ../mxml
endif

# MySQL
MYSQL_CONFIG := $(shell which mysql_config 2> /dev/null)
ifdef MYSQL_CONFIG
MYSQLINCDIR := $(shell mysql_config --cflags | sed -e 's,^.*-I\([^ ]*\).*$$,\1,' -e s/\'//g)
NEED_MYSQL  := $(shell if test -e $(MYSQLINCDIR)/mysql.h ; then echo 1; fi) 
endif

###########################################################################
## Check OS Type for OS-specified flags

OSTYPE = $(shell uname | tr '[A-Z]' '[a-z]')

ifeq ($(OSTYPE), linux)
# > 2GB file support
CFLAGS  += -D_LARGEFILE64_SOURCE
CFLAGS  += -DOS_LINUX -fPIC -Wno-unused-function
LDFLAGS += -lutil -lpthread
NEED_ZLIB        =1
SPECIFIC_OS_PRG += mlxspeaker dio
endif

ifeq ($(OSTYPE), osf1)
CFLAGS  += -DOS_OSF1
FFLAGS  += -nofor_main -D 40000000 -T 20000000
LDFLAGS += -lc -lbsd
endif

ifeq ($(OSTYPE), ultrix)
CFLAGS  += -DOS_ULTRIX -DNO_PTY
endif

ifeq ($(OSTYPE), freebsd)
CFLAGS  += -DOS_FREEBSD
LDFLAGS += -lbsd -lcompat
endif

ifeq ($(OSTYPE), darwin)
CFLAGS  += -DOS_LINUX -DOS_DARWIN -DHAVE_STRLCPY -fPIC -Wno-unused-function
LDFLAGS += -lpthread
NEED_RANLIB      = 1
SPECIFIC_OS_PRG += mlxspeaker
endif

ifeq ($(OSTYPE), cygwin_nt-5.1)
OSTYPE = cygwin
endif

ifeq ($(OSTYPE), cygwin)
CFLAGS  += -DOS_LINUX -DOS_CYGWIN -Wno-unused-function
LDFLAGS += -lutil -lpthread
endif

ifeq ($(OSTYPE), solaris)
CFLAGS  += -DOS_SOLARIS
LDFLAGS += -lsocket -lnsl
endif

###########################################################################
## Processing environment for building flags

CFLAGS += $(MIDAS_PREF_FLAGS) $(USERFLAGS)

ifdef MIDAS_MAX_EVENT_SIZE
CFLAGS += -DMAX_EVENT_SIZE=$(MIDAS_MAX_EVENT_SIZE)
endif # MIDAS_MAX_EVENT_SIZE

ifdef NEED_MYSQL
CFLAGS  += -DHAVE_MYSQL $(shell $(MYSQL_CONFIG) --include)
LDFLAGS += $(shell $(MYSQL_CONFIG) --libs)
NEED_ZLIB =1
endif # NEED_MYSQL

ifdef ROOTSYS
ROOTLIBS    := $(shell $(ROOTSYS)/bin/root-config --libs)
ROOTCFLAGS  := $(shell $(ROOTSYS)/bin/root-config --cflags)

ifdef NEED_RPATH
ROOTLIBS   += -Wl,-rpath,$(ROOTSYS)/lib
endif

ifdef NEED_LIBROOTA
ROOTLIBS    := $(ROOTSYS)/lib/libRoot.a -lssl -ldl -lcrypt
endif

CFLAGS += $(ROOTCFLAGS)
endif # ROOTSYS

ifdef NEED_ZLIB
CFLAGS     += -DHAVE_ZLIB
LIBS       += -lz
endif # ZLIB

ifdef NEED_SHLIB
CFLAGS  += -shared -fPIC
endif # SHLIB

###########################################################################
## Processing building targets

## Directories needed

INC_DIR = include
SRC_DIR = src
UTL_DIR = utils
DRV_DIR = drivers
EXM_DIR = examples

## Driectories which will be created

OS_DIR  = $(OSTYPE)
LIB_DIR = $(OS_DIR)/lib
BIN_DIR = $(OS_DIR)/bin
DIRS    = $(OS_DIR)  $(LIB_DIR)  $(BIN_DIR)

CFLAGS += -I$(INC_DIR) -I$(DRV_DIR) -I$(MXML_DIR) -L$(LIB_DIR)

## Directories for install

INSTDIR_BIN = $(PREFIX)/bin
INSTDIR_INC = $(PREFIX)/include
INSTDIR_LIB = $(PREFIX)/lib
INSTDIR_DRV = $(PREFIX)/driver

## Utilities

PROGS = mserver  mhttpd  mlogger  odbedit  mtape   mhist    \
	mstat    mcnaf   mdump    mhdump    mchart  odbhist  \
	melog    webpaw  lazylogger   stripchart.tcl  \
	$(SPECIFIC_OS_PRG)

UTILS = $(shell for i in $(PROGS); do echo $(BIN_DIR)/$$i ; done)

## Analyzer objects

ANALYZER  = $(LIB_DIR)/mana.o
ifdef CERNLIB
ANALYZER += $(LIB_DIR)/hmana.o
endif
ifdef ROOTSYS
ANALYZER += $(LIB_DIR)/rmana.o
endif

## Objects for building $(LIBMIDAS_A) and $(LIBMIDAS_SO)

OBJS_LIB_NEED = midas.o  system.o  mrpc.o  odb.o  ybos.o  ftplib.o  history.o  alarm.o  elog.o

ifndef NEED_SHLIB
OBJS_LIB_NEED += cnaf_callback.o
endif

OBJS_LIB = $(shell for i in $(OBJS_LIB_NEED) ; do echo $(LIB_DIR)/$$i ; done)

## MXML OBJS

MXML_OBJS_NEED = mxml.o
ifdef NEED_STRLCPY
MXML_OBJS_NEED += strlcpy.o
endif

MXML_OBJS = $(shell for i in $(MXML_OBJS_NEED) ; do echo $(LIB_DIR)/$$i ; done)

## Objects for install

OBJS_INS_NEED = mfe.o fal.o
OBJS_INS = $(shell for i in $(OBJS_INS_NEED) ; do echo $(LIB_DIR)/$$i ; done)

## library

LIBMIDAS_A  = $(LIB_DIR)/libmidas.a
ifdef NEED_SHLIB
LIBMIDAS_SO  = $(LIB_DIR)/libmidas.so
LDFLAGS     += -shared -L$(LIB_DIR) -lmidas
endif

## Examples

EXAMPLES_NEED = consume produce rpc_test msgdump minife minirc odb_test
EXAMPLES = $(shell for i in $(EXAMPLES_NEED); do echo examples/$$i ; done)

## Includes

INCLUDES = $(wildcard $(INC_DIR)/*.h)

###########################################################################

CXXFLAGS  = $(CFLAGS)
ifdef ROOTSYS
CXXFLAGS += -DHAVE_ROOT
endif

all: check-mxml mkdirs $(LIBMIDAS_A) $(LIBMIDAS_SO) $(ANALYZER) $(OBJS_INS) utilities

.PHONY: clean

###########################################################################

## Library objects

$(LIB_DIR)/%.o: $(SRC_DIR)/%.c $(INCLUDES)
	$(CC) $(CFLAGS) -c -o $@ $<

## MXML_OBJS

$(LIB_DIR)/mxml.o: $(MXML_DIR)/mxml.c
	$(CC) $(CFLAGS) -c -o $@ $<

$(LIB_DIR)/strlcpy.o: $(MXML_DIR)/strlcpy.c
	$(CC) $(CFLAGS) -c -o $@ $<

## Frontend and backend framework

$(LIB_DIR)/fal.o: $(SRC_DIR)/fal.c $(INCLUDES)
	$(CXX) -Dextname -DMANA_LITE -c -o $@ $< $(CFLAGS)

$(LIB_DIR)/hmana.o: $(SRC_DIR)/mana.c $(INCLUDES)
	$(CC) -Dextname -DHAVE_HBOOK $(CFLAGS) -c -o $@ $<

$(LIB_DIR)/rmana.o: $(SRC_DIR)/mana.c $(INCLUDES)
	$(CXX) -DUSE_ROOT $(CXXFLAGS) -c -o $@ $<

## Utilities

$(BIN_DIR)/%: $(UTL_DIR)/%.c $(INCLUDES)
	$(CC) $(CFLAGS) -o $@ $< $(LIBMIDAS_A) $(LDFLAGS)

$(BIN_DIR)/mlogger: $(SRC_DIR)/mlogger.c $(LIBMIDAS_A)
	$(CXX) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) $(ROOTLIBS)
$(BIN_DIR)/mserver: $(SRC_DIR)/mserver.c $(INCLUDES)
$(BIN_DIR)/mhttpd:  $(SRC_DIR)/mhttpd.c  $(SRC_DIR)/mgd.c
$(BIN_DIR)/odbedit: $(SRC_DIR)/odbedit.c $(SRC_DIR)/cmdedit.c
$(BIN_DIR)/mcnaf:   $(UTL_DIR)/mcnaf.c   $(DRV_DIR)/camac/camacrpc.c
$(BIN_DIR)/mhdump:  $(UTL_DIR)/mhdump.cxx
	$(CXX) $(CXXFLAGS) -o $@ $< $(LDFLAGS) $(ROOTLIBS)
$(BIN_DIR)/lazylogger: $(SRC_DIR)/lazylogger.c
$(BIN_DIR)/stripchart.tcl: $(UTL_DIR)/stripchart.tcl
	@cp -f $< $(BIN_DIR)/$(shell basename $@)

###########################################################################

mkdirs:
	@for i in $(DIRS) ; do \
		echo "Making directory $$i ..." ; \
		mkdir -p $$i ; \
	done
... 108 more lines ...
  456   09 Mar 2008 Stefan RittSuggestionNew Makefile for building MIDAS
> I rewrote the Makefile for MIDAS in order to make it tidy. I tested it on my box
> and it works here.
> 1. The full file is seperated to several parts
>   a. initialized setup
>   b. environment setup
>   c. specify OS-specific flags
>   d. processing environment for building flags
>   e. targets
> 2. The file is less than 400 lines now. The original one is more than 500 lines.
> 3. The modified one is easy for debuging.
> 
> I tried to learn "autoconf" and "automake" in order to make building MIDAS more
> compatible for various platforms. But I havn't enough time now. Hope somebody
> can help it. The attached file is original named "Makefile.in" for using "autoconf".

I think it is a good idea to cleanup the Makefile. It grew over many years and certainly
had some inconsistencies. We did however not use "autoconf" since it is not of much use.
It is meant for systems where small differences between different Unix flavors are
covered by this system, but the midas source code is supposed not only to run on Unix,
but also on vxWorks and Windows. As you can imagine, the differences are much more
severe and a simple makefile generator cannot cover the details. Furthermore, under
Windows there is no such thing like autoconf. So all the work to make the source code
compile on all systems has been put into system.c using conditional compiling. So
putting another abstraction layer on this would maybe more complicate things than
simplify it. I will test your Makefile, and I also ask the guys at TRIUMF to do so. Once
we conclude that it works fine, we can replace the original Makefile from the distribution.
  458   10 Mar 2008 Stefan RittSuggestionNew Makefile for building MIDAS
> I rewrote the Makefile for MIDAS in order to make it tidy. I tested it on my box
> and it works here.
> 1. The full file is seperated to several parts
>   a. initialized setup
>   b. environment setup
>   c. specify OS-specific flags
>   d. processing environment for building flags
>   e. targets
> 2. The file is less than 400 lines now. The original one is more than 500 lines.
> 3. The modified one is easy for debuging.
> 
> I tried to learn "autoconf" and "automake" in order to make building MIDAS more
> compatible for various platforms. But I havn't enough time now. Hope somebody
> can help it. The attached file is original named "Makefile.in" for using "autoconf".

The Makefile is missing -lzip:

[ritt@pc5082 ~/midas]$ make -f Makefile-by-EL
Making directory linux ...
Making directory linux/lib ...
Making directory linux/bin ...
g++ -g -O3 -Wall -Wuninitialized -DINCLUDE_FTPLIB -D_LARGEFILE64_SOURCE -DOS_LINUX -fPIC
-Wno-unused-function   -DHAVE_ZLIB -Iinclude -Idrivers -I../mxml -Llinux/lib -o
linux/bin/mlogger src/mlogger.c linux/lib/libmidas.a -lutil -lpthread
/tmp/cceHnAKe.o(.text+0x83c): In function `midas_flush_buffer(LOG_CHN*)':
src/mlogger.c:984: undefined reference to `gzwrite'
/tmp/cceHnAKe.o(.text+0xb24): In function `midas_log_open(LOG_CHN*, int)':
src/mlogger.c:1132: undefined reference to `gzopen'
/tmp/cceHnAKe.o(.text+0xb46):src/mlogger.c:1140: undefined reference to `gzsetparams'
/tmp/cceHnAKe.o(.text+0xe2a): In function `midas_log_close(LOG_CHN*, int)':
src/mlogger.c:1208: undefined reference to `gzflush'
/tmp/cceHnAKe.o(.text+0xe40):src/mlogger.c:1210: undefined reference to `gzclose'
collect2: ld returned 1 exit status
make: *** [linux/bin/mlogger] Error 1
[ritt@pc5082 ~/midas]$
ELOG V3.1.4-2e1708b5